mirror of
https://github.com/holub/mame
synced 2025-05-29 00:53:09 +03:00
MC680x0 update
- Reworked PMMU/core interface so PMMU now sees all cop 0 instructions - Improved disassembly of PMMU instructions - Preliminary 68LC040 support - Fixed disassembly for EC/LC variants of '030/'040
This commit is contained in:
parent
e3dfa2d83e
commit
fa216ba6f9
@ -976,7 +976,7 @@ endif
|
||||
|
||||
# rule to ensure we build the header before building the core CPU file
|
||||
$(CPUOBJ)/m68000/m68kcpu.o: $(CPUOBJ)/m68000/m68kops.c \
|
||||
$(CPUSRC)/m68000/m68kcpu.h
|
||||
$(CPUSRC)/m68000/m68kcpu.h $(CPUSRC)/m68000/m68kfpu.c $(CPUSRC)/m68000/m68kmmu.h
|
||||
|
||||
|
||||
|
||||
|
@ -29,6 +29,7 @@ enum
|
||||
M68K_CPU_TYPE_68EC030,
|
||||
M68K_CPU_TYPE_68030,
|
||||
M68K_CPU_TYPE_68EC040,
|
||||
M68K_CPU_TYPE_68LC040,
|
||||
M68K_CPU_TYPE_68040,
|
||||
M68K_CPU_TYPE_SCC68070
|
||||
};
|
||||
@ -93,6 +94,7 @@ CPU_GET_INFO( scc68070 );
|
||||
#define CPU_M68EC030 CPU_GET_INFO_NAME( m68ec030 )
|
||||
#define CPU_M68030 CPU_GET_INFO_NAME( m68030 )
|
||||
#define CPU_M68EC040 CPU_GET_INFO_NAME( m68ec040 )
|
||||
#define CPU_M68LC040 CPU_GET_INFO_NAME( m68lc040 )
|
||||
#define CPU_M68040 CPU_GET_INFO_NAME( m68040 )
|
||||
|
||||
#define CPU_SCC68070 CPU_GET_INFO_NAME( scc68070 )
|
||||
|
@ -262,6 +262,7 @@ M68KMAKE_OPCODE_HANDLER_HEADER
|
||||
#include "mame.h"
|
||||
extern void m68040_fpu_op0(m68ki_cpu_core *m68k);
|
||||
extern void m68040_fpu_op1(m68ki_cpu_core *m68k);
|
||||
extern void m68881_mmu_ops(m68ki_cpu_core *m68k);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ========================= INSTRUCTION HANDLERS ========================= */
|
||||
@ -748,7 +749,7 @@ pack 16 mm axy7 1000111101001111 .......... . . U U U . . 13 1
|
||||
pack 16 mm . 1000...101001... .......... . . U U U . . 13 13 13
|
||||
pea 32 . . 0100100001...... A..DXWLdx. U U U U U 6 6 5 5 5
|
||||
pflush 32 . . 1111010100011000 .......... . . . . S . . . . 4 TODO: correct timing
|
||||
pmove 32 . . 1111000000...... A..DXWLdx. . . S S S . . 8 8 8
|
||||
pmmu 32 . . 1111000......... .......... . . S S S . . 8 8 8
|
||||
reset 0 . . 0100111001110000 .......... S S S S S 0 0 0 0 0
|
||||
ror 8 s . 1110...000011... .......... U U U U U 6 6 8 8 8
|
||||
ror 16 s . 1110...001011... .......... U U U U U 6 6 8 8 8
|
||||
@ -7994,126 +7995,21 @@ M68KMAKE_OP(pea, 32, ., .)
|
||||
m68ki_push_32(m68k, ea);
|
||||
}
|
||||
|
||||
|
||||
M68KMAKE_OP(pflush, 32, ., .)
|
||||
{
|
||||
if ((CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type)) && (m68k->has_pmmu))
|
||||
{
|
||||
logerror("680x0: unhandled PFLUSH\n");
|
||||
logerror("68040: unhandled PFLUSH\n");
|
||||
return;
|
||||
}
|
||||
m68ki_exception_1111(m68k);
|
||||
}
|
||||
|
||||
M68KMAKE_OP(pmove, 32, ., .)
|
||||
M68KMAKE_OP(pmmu, 32, ., .)
|
||||
{
|
||||
UINT16 modes;
|
||||
UINT32 ea;
|
||||
|
||||
if ((CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type)) && (m68k->has_pmmu))
|
||||
{
|
||||
modes = m68ki_read_imm_16(m68k);
|
||||
ea = M68KMAKE_GET_EA_AY_32;
|
||||
|
||||
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
||||
{
|
||||
logerror("680x0: unhandled PLOAD\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xe200) == 0x2000) // PFLUSHA
|
||||
{
|
||||
logerror("680x0: unhandled PFLUSHA\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((modes>>13) & 0x7)
|
||||
{
|
||||
case 0: // MC68030/040 form with FD bit
|
||||
case 2: // MC68881 form, FD never set
|
||||
if (modes & 0x200)
|
||||
{
|
||||
switch ((modes>>10) & 7)
|
||||
{
|
||||
case 0: // translation control register
|
||||
memory_write_word_32be(m68k->program, ea, m68k->mmu_tc>>16);
|
||||
memory_write_word_32be(m68k->program, ea+2, m68k->mmu_tc&0xffff);
|
||||
break;
|
||||
|
||||
case 2: // supervisor root pointer
|
||||
memory_write_word_32be(m68k->program, ea, m68k->mmu_srp_limit>>16);
|
||||
memory_write_word_32be(m68k->program, ea+2, m68k->mmu_srp_limit&0xffff);
|
||||
memory_write_word_32be(m68k->program, ea+4, m68k->mmu_srp_aptr>>16);
|
||||
memory_write_word_32be(m68k->program, ea+6, m68k->mmu_srp_aptr&0xffff);
|
||||
break;
|
||||
|
||||
case 3: // CPU root pointer
|
||||
memory_write_word_32be(m68k->program, ea, m68k->mmu_crp_limit>>16);
|
||||
memory_write_word_32be(m68k->program, ea+2, m68k->mmu_crp_limit&0xffff);
|
||||
memory_write_word_32be(m68k->program, ea+4, m68k->mmu_crp_aptr>>16);
|
||||
memory_write_word_32be(m68k->program, ea+6, m68k->mmu_crp_aptr&0xffff);
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((modes>>10) & 7)
|
||||
{
|
||||
case 0: // translation control register
|
||||
m68k->mmu_tc = memory_read_word_32be(m68k->program, ea)<<16;
|
||||
m68k->mmu_tc |= memory_read_word_32be(m68k->program, ea+2);
|
||||
|
||||
if (m68k->mmu_tc & 0x80000000)
|
||||
{
|
||||
m68k->pmmu_enabled = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k->pmmu_enabled = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // supervisor root pointer
|
||||
m68k->mmu_srp_limit = memory_read_word_32be(m68k->program, ea)<<16;
|
||||
m68k->mmu_srp_limit |= memory_read_word_32be(m68k->program, ea+2);
|
||||
m68k->mmu_srp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16;
|
||||
m68k->mmu_srp_aptr |= memory_read_word_32be(m68k->program, ea+6);
|
||||
break;
|
||||
|
||||
case 3: // CPU root pointer
|
||||
m68k->mmu_crp_limit = memory_read_word_32be(m68k->program, ea)<<16;
|
||||
m68k->mmu_crp_limit |= memory_read_word_32be(m68k->program, ea+2);
|
||||
m68k->mmu_crp_aptr = memory_read_word_32be(m68k->program, ea+4)<<16;
|
||||
m68k->mmu_crp_aptr |= memory_read_word_32be(m68k->program, ea+6);
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // MC68030 to/from status reg
|
||||
if (modes & 0x200)
|
||||
{
|
||||
memory_write_word_32be(m68k->program, ea, m68k->mmu_sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k->mmu_sr = memory_read_word_32be(m68k->program, ea);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
|
||||
break;
|
||||
}
|
||||
|
||||
m68881_mmu_ops(m68k);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
#if 0
|
||||
static const char copyright_notice[] =
|
||||
"MUSASHI\n"
|
||||
"Version 4.5 (2009-10-09)\n"
|
||||
"Version 4.55 (2009-10-31)\n"
|
||||
"A portable Motorola M680x0 processor emulation engine.\n"
|
||||
"Copyright Karl Stenerud. All rights reserved.\n"
|
||||
"\n"
|
||||
@ -42,6 +42,7 @@ static const char copyright_notice[] =
|
||||
|
||||
extern void m68040_fpu_op0(m68ki_cpu_core *m68k);
|
||||
extern void m68040_fpu_op1(m68ki_cpu_core *m68k);
|
||||
extern void m68881_mmu_ops(m68ki_cpu_core *m68k);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= DATA ================================= */
|
||||
@ -1720,7 +1721,7 @@ CPU_GET_INFO( m68040 )
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* M680EC30 section
|
||||
* M68EC040 section
|
||||
****************************************************************************/
|
||||
|
||||
static CPU_INIT( m68ec040 )
|
||||
@ -1762,6 +1763,49 @@ CPU_GET_INFO( m68ec040 )
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* M68LC040 section
|
||||
****************************************************************************/
|
||||
|
||||
static CPU_INIT( m68lc040 )
|
||||
{
|
||||
m68ki_cpu_core *m68k = get_safe_token(device);
|
||||
|
||||
CPU_INIT_CALL(m68k);
|
||||
|
||||
m68k->cpu_type = CPU_TYPE_LC040;
|
||||
m68k->state.subtypemask = m68k->cpu_type;
|
||||
m68k->dasm_type = M68K_CPU_TYPE_68LC040;
|
||||
m68k->memory = interface_d32;
|
||||
m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
m68k->cyc_instruction = m68ki_cycles[4];
|
||||
m68k->cyc_exception = m68ki_exception_cycle_table[4];
|
||||
m68k->cyc_bcc_notake_b = -2;
|
||||
m68k->cyc_bcc_notake_w = 0;
|
||||
m68k->cyc_dbcc_f_noexp = 0;
|
||||
m68k->cyc_dbcc_f_exp = 4;
|
||||
m68k->cyc_scc_r_true = 0;
|
||||
m68k->cyc_movem_w = 2;
|
||||
m68k->cyc_movem_l = 2;
|
||||
m68k->cyc_shift = 0;
|
||||
m68k->cyc_reset = 518;
|
||||
m68k->has_pmmu = 1;
|
||||
}
|
||||
|
||||
CPU_GET_INFO( m68lc040 )
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as pointers to data or functions --- */
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68lc040); break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "68LC040"); break;
|
||||
|
||||
default: CPU_GET_INFO_CALL(m68040); break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SCC-68070 section
|
||||
****************************************************************************/
|
||||
|
@ -81,8 +81,9 @@ typedef struct _m68ki_cpu_core m68ki_cpu_core;
|
||||
#define CPU_TYPE_EC030 (0x00000020)
|
||||
#define CPU_TYPE_030 (0x00000040)
|
||||
#define CPU_TYPE_EC040 (0x00000080)
|
||||
#define CPU_TYPE_040 (0x00000100)
|
||||
#define CPU_TYPE_SCC070 (0x00000200)
|
||||
#define CPU_TYPE_LC040 (0x00000100)
|
||||
#define CPU_TYPE_040 (0x00000200)
|
||||
#define CPU_TYPE_SCC070 (0x00000400)
|
||||
|
||||
/* Different ways to stop the CPU */
|
||||
#define STOP_LEVEL_STOP 1
|
||||
|
@ -146,6 +146,7 @@ UINT32 peek_imm_32(void);
|
||||
/* make signed integers 100% portably */
|
||||
static int make_int_8(int value);
|
||||
static int make_int_16(int value);
|
||||
static int make_int_32(int value);
|
||||
|
||||
/* make a string of a hex value */
|
||||
static char* make_signed_hex_str_8(UINT32 val);
|
||||
@ -230,6 +231,12 @@ static const char *const g_mmuregs[8] =
|
||||
"tc", "drp", "srp", "crp", "cal", "val", "sccr", "acr"
|
||||
};
|
||||
|
||||
static const char *const g_mmucond[16] =
|
||||
{
|
||||
"bs", "bc", "ls", "lc", "ss", "sc", "as", "ac",
|
||||
"ws", "wc", "is", "ic", "gs", "gc", "cs", "cc"
|
||||
};
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =========================== UTILITY FUNCTIONS ========================== */
|
||||
/* ======================================================================== */
|
||||
@ -304,6 +311,10 @@ static int make_int_16(int value)
|
||||
return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
|
||||
}
|
||||
|
||||
static int make_int_32(int value)
|
||||
{
|
||||
return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
|
||||
}
|
||||
|
||||
/* Get string representation of hex values */
|
||||
static char* make_signed_hex_str_8(UINT32 val)
|
||||
@ -2563,6 +2574,7 @@ static void d68000_pea(void)
|
||||
sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir));
|
||||
}
|
||||
|
||||
// this is a 68040-specific form of PFLUSH
|
||||
static void d68040_pflush(void)
|
||||
{
|
||||
LIMIT_CPU_TYPES(M68040_PLUS);
|
||||
@ -3019,7 +3031,16 @@ static void d68020_unpk_mm(void)
|
||||
}
|
||||
|
||||
|
||||
static void d68030_pmove(void)
|
||||
// PFLUSH: 001xxx0xxxxxxxxx
|
||||
// PLOAD: 001000x0000xxxxx
|
||||
// PVALID1: 0010100000000000
|
||||
// PVALID2: 0010110000000xxx
|
||||
// PMOVE 1: 010xxxx000000000
|
||||
// PMOVE 2: 011xxxx0000xxx00
|
||||
// PMOVE 3: 011xxxx000000000
|
||||
// PTEST: 100xxxxxxxxxxxxx
|
||||
// PFLUSHR: 1010000000000000
|
||||
static void d68851_p000(void)
|
||||
{
|
||||
char* str;
|
||||
UINT16 modes = read_imm_16();
|
||||
@ -3040,16 +3061,32 @@ static void d68030_pmove(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xe200) == 0x2000) // PFLUSHA
|
||||
if ((modes & 0xe200) == 0x2000) // PFLUSH
|
||||
{
|
||||
if (modes & 0x0200)
|
||||
{
|
||||
sprintf(g_dasm_str, "pflush %s, %s", g_mmuregs[(modes>>10)&7], str);
|
||||
sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (modes == 0xa000) // PFLUSHR
|
||||
{
|
||||
sprintf(g_dasm_str, "pflush %s, %s", str, g_mmuregs[(modes>>10)&7]);
|
||||
sprintf(g_dasm_str, "pflushr %s", str);
|
||||
}
|
||||
|
||||
if (modes == 0x2800) // PVALID (FORMAT 1)
|
||||
{
|
||||
sprintf(g_dasm_str, "pvalid VAL, %s", str);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
|
||||
{
|
||||
sprintf(g_dasm_str, "pvalid A%d, %s", modes & 0xf, str);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xe000) == 0x8000) // PTEST
|
||||
{
|
||||
sprintf(g_dasm_str, "ptest #%d, %s", modes & 0x1f, str);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3098,6 +3135,33 @@ static void d68030_pmove(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void d68851_pbcc16(void)
|
||||
{
|
||||
UINT32 temp_pc = g_cpu_pc;
|
||||
|
||||
sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_16(read_imm_16()));
|
||||
}
|
||||
|
||||
static void d68851_pbcc32(void)
|
||||
{
|
||||
UINT32 temp_pc = g_cpu_pc;
|
||||
|
||||
sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_32(read_imm_32()));
|
||||
}
|
||||
|
||||
static void d68851_pdbcc(void)
|
||||
{
|
||||
UINT32 temp_pc = g_cpu_pc;
|
||||
UINT16 modes = read_imm_16();
|
||||
|
||||
sprintf(g_dasm_str, "pb%s %x", g_mmucond[modes&0xf], temp_pc + make_int_16(read_imm_16()));
|
||||
}
|
||||
|
||||
// PScc: 0000000000xxxxxx
|
||||
static void d68851_p001(void)
|
||||
{
|
||||
sprintf(g_dasm_str, "MMU 001 group");
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ======================= INSTRUCTION TABLE BUILDER ====================== */
|
||||
@ -3421,7 +3485,11 @@ static const opcode_struct g_opcode_info[] =
|
||||
{d68000_unlk , 0xfff8, 0x4e58, 0x000},
|
||||
{d68020_unpk_rr , 0xf1f8, 0x8180, 0x000},
|
||||
{d68020_unpk_mm , 0xf1f8, 0x8188, 0x000},
|
||||
{d68030_pmove , 0xffc0, 0xf000, 0x278},
|
||||
{d68851_p000 , 0xffc0, 0xf000, 0x000},
|
||||
{d68851_pbcc16 , 0xffc0, 0xf080, 0x000},
|
||||
{d68851_pbcc32 , 0xffc0, 0xf0c0, 0x000},
|
||||
{d68851_pdbcc , 0xfff8, 0xf048, 0x000},
|
||||
{d68851_p001 , 0xffc0, 0xf040, 0x000},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -3551,15 +3619,16 @@ static unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned i
|
||||
g_cpu_type = TYPE_68010;
|
||||
break;
|
||||
case M68K_CPU_TYPE_68EC020:
|
||||
g_cpu_type = TYPE_68020;
|
||||
break;
|
||||
case M68K_CPU_TYPE_68020:
|
||||
g_cpu_type = TYPE_68020;
|
||||
break;
|
||||
case M68K_CPU_TYPE_68EC030:
|
||||
case M68K_CPU_TYPE_68030:
|
||||
g_cpu_type = TYPE_68030;
|
||||
break;
|
||||
case M68K_CPU_TYPE_68040:
|
||||
case M68K_CPU_TYPE_68EC040:
|
||||
case M68K_CPU_TYPE_68LC040:
|
||||
g_cpu_type = TYPE_68040;
|
||||
break;
|
||||
default:
|
||||
@ -3752,6 +3821,7 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
|
||||
case M68K_CPU_TYPE_68EC020:
|
||||
case M68K_CPU_TYPE_68020:
|
||||
case M68K_CPU_TYPE_68030:
|
||||
case M68K_CPU_TYPE_68EC030:
|
||||
if(g_instruction_table[instruction] == d68040_cinv)
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68040_cpush)
|
||||
@ -3766,9 +3836,9 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68040_move16_al_ai)
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68040_pflush)
|
||||
return 0;
|
||||
case M68K_CPU_TYPE_68040:
|
||||
case M68K_CPU_TYPE_68EC040:
|
||||
case M68K_CPU_TYPE_68LC040:
|
||||
if(g_instruction_table[instruction] == d68020_cpbcc_16)
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68020_cpbcc_32)
|
||||
@ -3789,6 +3859,8 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68020_cptrapcc_32)
|
||||
return 0;
|
||||
if(g_instruction_table[instruction] == d68040_pflush)
|
||||
return 0;
|
||||
}
|
||||
if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 &&
|
||||
(g_instruction_table[instruction] == d68020_callm ||
|
||||
|
@ -95,6 +95,11 @@ static UINT8 READ_EA_8(m68ki_cpu_core *m68k, int ea)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 0: // (xxx).W
|
||||
{
|
||||
UINT32 ea = (UINT32)OPER_I_16(m68k);
|
||||
return m68ki_read_8(m68k, ea);
|
||||
}
|
||||
case 1: // (xxx).L
|
||||
{
|
||||
UINT32 d1 = OPER_I_16(m68k);
|
||||
@ -146,6 +151,11 @@ static UINT16 READ_EA_16(m68ki_cpu_core *m68k, int ea)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 0: // (xxx).W
|
||||
{
|
||||
UINT32 ea = (UINT32)OPER_I_16(m68k);
|
||||
return m68ki_read_16(m68k, ea);
|
||||
}
|
||||
case 1: // (xxx).L
|
||||
{
|
||||
UINT32 d1 = OPER_I_16(m68k);
|
||||
@ -203,6 +213,11 @@ static UINT32 READ_EA_32(m68ki_cpu_core *m68k, int ea)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 0: // (xxx).W
|
||||
{
|
||||
UINT32 ea = (UINT32)OPER_I_16(m68k);
|
||||
return m68ki_read_32(m68k, ea);
|
||||
}
|
||||
case 1: // (xxx).L
|
||||
{
|
||||
UINT32 d1 = OPER_I_16(m68k);
|
||||
@ -228,6 +243,63 @@ static UINT32 READ_EA_32(m68ki_cpu_core *m68k, int ea)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT64 READ_EA_64(m68ki_cpu_core *m68k, 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(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 3: // (An)+
|
||||
{
|
||||
UINT32 ea = REG_A[reg];
|
||||
REG_A[reg] += 8;
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 5: // (d16, An)
|
||||
{
|
||||
UINT32 ea = EA_AY_DI_32(m68k);
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 4: // #<data>
|
||||
{
|
||||
h1 = OPER_I_32(m68k);
|
||||
h2 = OPER_I_32(m68k);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 2: // (d16, PC)
|
||||
{
|
||||
UINT32 ea = EA_PCDI_32(m68k);
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, 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_8(m68ki_cpu_core *m68k, int ea, UINT8 data)
|
||||
{
|
||||
int mode = (ea >> 3) & 0x7;
|
||||
@ -376,6 +448,11 @@ static void WRITE_EA_32(m68ki_cpu_core *m68k, int ea, UINT32 data)
|
||||
REG_D[reg] = data;
|
||||
break;
|
||||
}
|
||||
case 1: // An
|
||||
{
|
||||
REG_A[reg] = data;
|
||||
break;
|
||||
}
|
||||
case 2: // (An)
|
||||
{
|
||||
UINT32 ea = REG_A[reg];
|
||||
@ -432,63 +509,6 @@ static void WRITE_EA_32(m68ki_cpu_core *m68k, int ea, UINT32 data)
|
||||
}
|
||||
}
|
||||
|
||||
static UINT64 READ_EA_64(m68ki_cpu_core *m68k, 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(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 3: // (An)+
|
||||
{
|
||||
UINT32 ea = REG_A[reg];
|
||||
REG_A[reg] += 8;
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 5: // (d16, An)
|
||||
{
|
||||
UINT32 ea = EA_AY_DI_32(m68k);
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, ea+4);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 4: // #<data>
|
||||
{
|
||||
h1 = OPER_I_32(m68k);
|
||||
h2 = OPER_I_32(m68k);
|
||||
return (UINT64)(h1) << 32 | (UINT64)(h2);
|
||||
}
|
||||
case 2: // (d16, PC)
|
||||
{
|
||||
UINT32 ea = EA_PCDI_32(m68k);
|
||||
h1 = m68ki_read_32(m68k, ea+0);
|
||||
h2 = m68ki_read_32(m68k, 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(m68ki_cpu_core *m68k, int ea, UINT64 data)
|
||||
{
|
||||
int mode = (ea >> 3) & 0x7;
|
||||
|
@ -3,7 +3,7 @@
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 4.10
|
||||
* Version 4.55
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
@ -55,7 +55,7 @@
|
||||
*/
|
||||
|
||||
|
||||
static const char g_version[] = "4.10";
|
||||
static const char g_version[] = "4.55";
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== INCLUDES =============================== */
|
||||
@ -767,7 +767,7 @@ static void write_body(FILE* filep, body_struct* body, replace_struct* replace)
|
||||
}
|
||||
/* Found a directive with no matching replace string */
|
||||
if(!found)
|
||||
error_exit("Unknown " ID_BASE " directive");
|
||||
error_exit("Unknown " ID_BASE " directive [%s]", output);
|
||||
}
|
||||
fprintf(filep, "%s\n", output);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
||||
{
|
||||
UINT32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0;
|
||||
UINT32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0;
|
||||
UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits;
|
||||
UINT32 resolved, tptr, shift;
|
||||
|
||||
@ -108,15 +108,34 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
||||
// if table A wasn't early-out, continue to process table B
|
||||
if (!resolved)
|
||||
{
|
||||
// get table C offset and pointer
|
||||
tofs = (addr_in<<(is+abits+bbits))>>(32-cbits);
|
||||
tptr = tbl_entry & 0xfffffff0;
|
||||
|
||||
switch (tbmode)
|
||||
{
|
||||
case 0: // invalid, should cause MMU exception
|
||||
case 2: // 4-byte table C descriptor
|
||||
case 3: // 8-byte table C descriptor
|
||||
fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x)\n", tbmode, addr_in);
|
||||
fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, m68k->pc);
|
||||
break;
|
||||
|
||||
case 1: // early termination descriptor
|
||||
case 2: // 4-byte table C descriptor
|
||||
tofs *= 4;
|
||||
// logerror("PMMU: reading table C entry at %08x\n", tofs + tptr);
|
||||
tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr);
|
||||
tcmode = tbl_entry & 3;
|
||||
// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
|
||||
break;
|
||||
|
||||
case 3: // 8-byte table C descriptor
|
||||
tofs *= 8;
|
||||
// logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
|
||||
tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr);
|
||||
tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4);
|
||||
tcmode = tbl_entry2 & 3;
|
||||
// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
|
||||
break;
|
||||
|
||||
case 1: // termination descriptor
|
||||
tbl_entry &= 0xffffff00;
|
||||
|
||||
shift = is+abits+bbits;
|
||||
@ -126,55 +145,176 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
|
||||
}
|
||||
}
|
||||
|
||||
// if ((addr_in < 0x40000000) || (addr_in > 0x4fffffff)) printf("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
|
||||
if (!resolved)
|
||||
{
|
||||
switch (tcmode)
|
||||
{
|
||||
case 0: // invalid, should cause MMU exception
|
||||
case 2: // 4-byte ??? descriptor
|
||||
case 3: // 8-byte ??? descriptor
|
||||
fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, m68k->pc);
|
||||
break;
|
||||
|
||||
case 1: // termination descriptor
|
||||
tbl_entry &= 0xffffff00;
|
||||
|
||||
shift = is+abits+bbits+cbits;
|
||||
addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
|
||||
resolved = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// logerror("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
|
||||
|
||||
return addr_out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
maincpu at 40804366: called unimplemented instruction f000 (cpgen)
|
||||
PMMU: tcr 80f05570 limit 7fff0003 aptr 043ffcc0 is 0
|
||||
PMMU: reading table A entries at 043ffce0
|
||||
PMMU: addr 4080438a entry 00000000 entry2 7ffffc18 mode 0 aofs 20
|
||||
680x0 PMMU: Unhandled Table A mode 0
|
||||
|
||||
enable, PS = f
|
||||
|
||||
tblA @ 043ffcc0:
|
||||
|
||||
043ffcc0 0001fc0a 043ffcb0 => 00000019 04000019
|
||||
043ffcc8 7ffffc18 00000000
|
||||
043ffcd0 7ffffc18 00000000
|
||||
043ffcd8 7ffffc18 00000000
|
||||
043ffce0 7ffffc18 00000000
|
||||
043ffce8 7ffffc18 00000000
|
||||
043ffcf0 7ffffc18 00000000
|
||||
043ffcf8 7ffffc18 00000000
|
||||
043ffd00 7ffffc19 40000000
|
||||
043ffd08 7ffffc19 48000000
|
||||
043ffd10 7ffffc59 50000000
|
||||
043ffd18 7ffffc59 58000000
|
||||
043ffd20 7ffffc59 60000000
|
||||
043ffd28 7ffffc59 68000000
|
||||
043ffd30 7ffffc59 70000000
|
||||
043ffd38 7ffffc59 78000000
|
||||
043ffd40 7ffffc59 80000000
|
||||
043ffd48 7ffffc59 88000000
|
||||
043ffd50 7ffffc59 90000000
|
||||
043ffd58 7ffffc59 98000000
|
||||
043ffd60 7ffffc59 a0000000
|
||||
043ffd68 7ffffc59 a8000000
|
||||
043ffd70 7ffffc59 b0000000
|
||||
043ffd78 7ffffc59 b8000000
|
||||
043ffd80 7ffffc59 c0000000
|
||||
043ffd88 7ffffc59 c8000000
|
||||
043ffd90 7ffffc59 d0000000
|
||||
043ffd98 7ffffc59 d8000000
|
||||
043ffda0 7ffffc59 e0000000
|
||||
043ffda8 7ffffc59 e8000000
|
||||
043ffdb0 7ffffc59 f0000000
|
||||
043ffdb8 7ffffc59 f8000000
|
||||
m68881_mmu_ops: COP 0 MMU opcode handling
|
||||
|
||||
*/
|
||||
|
||||
void m68881_mmu_ops(m68ki_cpu_core *m68k)
|
||||
{
|
||||
UINT16 modes;
|
||||
UINT32 ea = m68k->ir & 0x3f;
|
||||
UINT64 temp64;
|
||||
|
||||
// catch the 2 "weird" encodings up front (PBcc)
|
||||
if ((m68k->ir & 0xffc0) == 0xf0c0)
|
||||
{
|
||||
logerror("680x0: unhandled PBcc\n");
|
||||
return;
|
||||
}
|
||||
else if ((m68k->ir & 0xffc0) == 0xf080)
|
||||
{
|
||||
logerror("680x0: unhandled PBcc\n");
|
||||
return;
|
||||
}
|
||||
else // the rest are 1111000xxxXXXXXX where xxx is the instruction family
|
||||
{
|
||||
switch ((m68k->ir>>9) & 0x7)
|
||||
{
|
||||
case 0:
|
||||
modes = OPER_I_16(m68k);
|
||||
|
||||
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
||||
{
|
||||
logerror("680x0: unhandled PLOAD\n");
|
||||
return;
|
||||
}
|
||||
else if ((modes & 0xe200) == 0x2000) // PFLUSH
|
||||
{
|
||||
logerror("680x0: unhandled PFLUSH PC=%x\n", m68k->pc);
|
||||
return;
|
||||
}
|
||||
else if (modes == 0xa000) // PFLUSHR
|
||||
{
|
||||
logerror("680x0: unhandled PFLUSHR\n");
|
||||
return;
|
||||
}
|
||||
else if (modes == 0x2800) // PVALID (FORMAT 1)
|
||||
{
|
||||
logerror("680x0: unhandled PVALID1\n");
|
||||
return;
|
||||
}
|
||||
else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
|
||||
{
|
||||
logerror("680x0: unhandled PVALID2\n");
|
||||
return;
|
||||
}
|
||||
else if ((modes & 0xe000) == 0x8000) // PTEST
|
||||
{
|
||||
logerror("680x0: unhandled PTEST\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((modes>>13) & 0x7)
|
||||
{
|
||||
case 0: // MC68030/040 form with FD bit
|
||||
case 2: // MC68881 form, FD never set
|
||||
if (modes & 0x200)
|
||||
{
|
||||
switch ((modes>>10) & 7)
|
||||
{
|
||||
case 0: // translation control register
|
||||
WRITE_EA_32(m68k, ea, m68k->mmu_tc);
|
||||
break;
|
||||
|
||||
case 2: // supervisor root pointer
|
||||
WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_srp_limit<<32 | (UINT64)m68k->mmu_srp_aptr);
|
||||
break;
|
||||
|
||||
case 3: // CPU root pointer
|
||||
WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_crp_limit<<32 | (UINT64)m68k->mmu_crp_aptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((modes>>10) & 7)
|
||||
{
|
||||
case 0: // translation control register
|
||||
m68k->mmu_tc = READ_EA_32(m68k, ea);
|
||||
|
||||
if (m68k->mmu_tc & 0x80000000)
|
||||
{
|
||||
m68k->pmmu_enabled = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k->pmmu_enabled = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // supervisor root pointer
|
||||
temp64 = READ_EA_64(m68k, ea);
|
||||
m68k->mmu_srp_limit = (temp64>>32) & 0xffffffff;
|
||||
m68k->mmu_srp_aptr = temp64 & 0xffffffff;
|
||||
break;
|
||||
|
||||
case 3: // CPU root pointer
|
||||
temp64 = READ_EA_64(m68k, ea);
|
||||
m68k->mmu_crp_limit = (temp64>>32) & 0xffffffff;
|
||||
m68k->mmu_crp_aptr = temp64 & 0xffffffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // MC68030 to/from status reg
|
||||
if (modes & 0x200)
|
||||
{
|
||||
WRITE_EA_32(m68k, ea, m68k->mmu_sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k->mmu_sr = READ_EA_32(m68k, ea);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("680x0: unknown PMMU instruction group %d\n", (m68k->ir>>9) & 0x7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user