diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 3a2331db258..51538622bcb 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -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 diff --git a/src/emu/cpu/m68000/m68000.h b/src/emu/cpu/m68000/m68000.h index a8682feee46..80eba3bb2e0 100644 --- a/src/emu/cpu/m68000/m68000.h +++ b/src/emu/cpu/m68000/m68000.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 ) diff --git a/src/emu/cpu/m68000/m68k_in.c b/src/emu/cpu/m68000/m68k_in.c index 328cb2a5594..21e2f060bea 100644 --- a/src/emu/cpu/m68000/m68k_in.c +++ b/src/emu/cpu/m68000/m68k_in.c @@ -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 { diff --git a/src/emu/cpu/m68000/m68kcpu.c b/src/emu/cpu/m68000/m68kcpu.c index 6c206383e2b..814afb0bd1d 100644 --- a/src/emu/cpu/m68000/m68kcpu.c +++ b/src/emu/cpu/m68000/m68kcpu.c @@ -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 ****************************************************************************/ diff --git a/src/emu/cpu/m68000/m68kcpu.h b/src/emu/cpu/m68000/m68kcpu.h index 6f8245b937c..d0b113b3b47 100644 --- a/src/emu/cpu/m68000/m68kcpu.h +++ b/src/emu/cpu/m68000/m68kcpu.h @@ -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 diff --git a/src/emu/cpu/m68000/m68kdasm.c b/src/emu/cpu/m68000/m68kdasm.c index 11940a375ae..a3c112983f6 100644 --- a/src/emu/cpu/m68000/m68kdasm.c +++ b/src/emu/cpu/m68000/m68kdasm.c @@ -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); - } - else - { - sprintf(g_dasm_str, "pflush %s, %s", str, g_mmuregs[(modes>>10)&7]); - } + sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str); + return; + } + + if (modes == 0xa000) // PFLUSHR + { + 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 || diff --git a/src/emu/cpu/m68000/m68kfpu.c b/src/emu/cpu/m68000/m68kfpu.c index 351c8775ae7..cad7d1da2e6 100644 --- a/src/emu/cpu/m68000/m68kfpu.c +++ b/src/emu/cpu/m68000/m68kfpu.c @@ -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: // # + { + 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: // # - { - 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; diff --git a/src/emu/cpu/m68000/m68kmake.c b/src/emu/cpu/m68000/m68kmake.c index d4359b4f04a..067988f877b 100644 --- a/src/emu/cpu/m68000/m68kmake.c +++ b/src/emu/cpu/m68000/m68kmake.c @@ -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); } diff --git a/src/emu/cpu/m68000/m68kmmu.h b/src/emu/cpu/m68000/m68kmmu.h index 33aec035654..3476202ca1b 100644 --- a/src/emu/cpu/m68000/m68kmmu.h +++ b/src/emu/cpu/m68000/m68kmmu.h @@ -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; @@ -37,7 +37,7 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in) bbits = (m68k->mmu_tc>>8)&0xf; cbits = (m68k->mmu_tc>>4)&0xf; -// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); +// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); // get table A offset tofs = (addr_in<>(32-abits); @@ -52,19 +52,19 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in) case 2: // valid 4 byte descriptors tofs *= 4; -// logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); +// logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)); tamode = tbl_entry & 3; -// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); +// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); break; case 3: // valid 8 byte descriptors tofs *= 8; -// logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); +// logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)); tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)+4); tamode = tbl_entry2 & 3; -// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); +// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); break; } @@ -81,19 +81,19 @@ INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in) case 2: // 4-byte table B descriptor tofs *= 4; -// logerror("PMMU: reading table B entry at %08x\n", tofs + tptr); +// logerror("PMMU: reading table B entry at %08x\n", tofs + tptr); tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr); tbmode = tbl_entry & 3; -// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); +// logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); break; case 3: // 8-byte table B descriptor tofs *= 8; -// logerror("PMMU: reading table B entries at %08x\n", tofs + tptr); +// logerror("PMMU: reading table B 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); tbmode = tbl_entry2 & 3; -// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); +// logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); break; case 1: // early termination descriptor @@ -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) + 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; + } + } +} +