m680x0 update:
- Added working PMMU address translation (not feature complete, but sufficient to boot several 68030 Macs in MESS) - Fixed up disassembly of some PMMU instructions - Added "68020 with 68851" CPU type
This commit is contained in:
parent
8126887721
commit
d5576b3797
7 changed files with 317 additions and 27 deletions
76
m68k_in.c
76
m68k_in.c
|
|
@ -8469,7 +8469,81 @@ M68KMAKE_OP(pmove, 32, ., .)
|
|||
modes = m68ki_read_imm_16();
|
||||
ea = M68KMAKE_GET_EA_AY_32;
|
||||
|
||||
fprintf(stderr,"680x0: unhandled PMOVE modes %x ea %x\n", modes, ea);
|
||||
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
||||
{
|
||||
fprintf(stderr,"680x0: unhandled PLOAD\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xe200) == 0x2000) // PFLUSHA
|
||||
{
|
||||
fprintf(stderr,"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)
|
||||
{
|
||||
fprintf(stderr,"680x0: PMOVE from MMU not supported\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((modes>>10) & 7)
|
||||
{
|
||||
case 0: // translation control register
|
||||
m68ki_cpu.mmu_tc = m68k_read_memory_16( ea)<<16;
|
||||
m68ki_cpu.mmu_tc |= m68k_read_memory_16( ea+2);
|
||||
|
||||
if (m68ki_cpu.mmu_tc & 0x80000000)
|
||||
{
|
||||
m68ki_cpu.pmmu_enabled = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m68ki_cpu.pmmu_enabled = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // supervisor root pointer
|
||||
m68ki_cpu.mmu_srp_limit = m68k_read_memory_16( ea)<<16;
|
||||
m68ki_cpu.mmu_srp_limit |= m68k_read_memory_16( ea+2);
|
||||
m68ki_cpu.mmu_srp_aptr = m68k_read_memory_16( ea+4)<<16;
|
||||
m68ki_cpu.mmu_srp_aptr |= m68k_read_memory_16( ea+6);
|
||||
break;
|
||||
|
||||
case 3: // CPU root pointer
|
||||
m68ki_cpu.mmu_crp_limit = m68k_read_memory_16( ea)<<16;
|
||||
m68ki_cpu.mmu_crp_limit |= m68k_read_memory_16( ea+2);
|
||||
m68ki_cpu.mmu_crp_aptr = m68k_read_memory_16( ea+4)<<16;
|
||||
m68ki_cpu.mmu_crp_aptr |= m68k_read_memory_16( ea+6);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"680x0: PMOVE to unknown MMU register %x\n", (modes>>10) & 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // MC68030 to/from status reg
|
||||
if (modes & 0x200)
|
||||
{
|
||||
m68k_write_memory_16(ea, m68ki_cpu.mmu_sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
m68ki_cpu.mmu_sr = m68k_read_memory_16( ea);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@
|
|||
#define M68K_LOG_1010_1111 OPT_OFF
|
||||
#define M68K_LOG_FILEHANDLE some_file_handle
|
||||
|
||||
/* Emulate PMMU : if you enable this, there will be a test to see if the current chip has some enabled pmmu added to every memory access,
|
||||
* so enable this only if it's useful */
|
||||
#define M68K_EMULATE_PMMU OPT_ON
|
||||
|
||||
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 4.10
|
||||
* Version 4.5
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
|
|
@ -597,7 +597,6 @@ static void default_instr_hook_callback(unsigned int pc)
|
|||
jmp_buf m68ki_aerr_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
/* ======================================================================== */
|
||||
|
|
@ -1046,6 +1045,9 @@ void m68k_init(void)
|
|||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
{
|
||||
/* Disable the PMMU on reset */
|
||||
m68ki_cpu.pmmu_enabled = 0;
|
||||
|
||||
/* Clear all stop levels and eat up all remaining cycles */
|
||||
CPU_STOPPED = 0;
|
||||
SET_CYCLES(0);
|
||||
|
|
@ -1088,7 +1090,6 @@ void m68k_pulse_halt(void)
|
|||
CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
}
|
||||
|
||||
|
||||
/* Get and set the current CPU context */
|
||||
/* This is to allow for multiple CPUs */
|
||||
unsigned int m68k_context_size()
|
||||
|
|
|
|||
16
m68kcpu.h
16
m68kcpu.h
|
|
@ -3,7 +3,7 @@
|
|||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.32
|
||||
* Version 4.5
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
|
|
@ -267,7 +267,11 @@ extern "C" {
|
|||
#endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */
|
||||
|
||||
/* Simulate address lines of 68k family */
|
||||
#if M68K_EMULATE_PMMU
|
||||
#define ADDRESS_68K(A) (PMMU_ENABLED ? pmmu_translate_addr((A)&CPU_ADDRESS_MASK) : ((A)&CPU_ADDRESS_MASK))
|
||||
#else
|
||||
#define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK)
|
||||
#endif
|
||||
|
||||
|
||||
/* Shift & Rotate Macros. */
|
||||
|
|
@ -369,6 +373,7 @@ extern "C" {
|
|||
#define CYC_SHIFT m68ki_cpu.cyc_shift
|
||||
#define CYC_RESET m68ki_cpu.cyc_reset
|
||||
#define HAS_PMMU m68ki_cpu.has_pmmu
|
||||
#define PMMU_ENABLED m68ki_cpu.pmmu_enabled
|
||||
#define RESET_CYCLES m68ki_cpu.reset_cycles
|
||||
|
||||
|
||||
|
|
@ -945,6 +950,7 @@ typedef struct
|
|||
uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
||||
uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
||||
int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */
|
||||
int pmmu_enabled; /* Indicates if the PMMU is enabled */
|
||||
uint reset_cycles;
|
||||
|
||||
/* Clocks required for instructions / exceptions */
|
||||
|
|
@ -962,6 +968,12 @@ typedef struct
|
|||
uint virq_state;
|
||||
uint nmi_pending;
|
||||
|
||||
/* PMMU registers */
|
||||
uint mmu_crp_aptr, mmu_crp_limit;
|
||||
uint mmu_srp_aptr, mmu_srp_limit;
|
||||
uint mmu_tc;
|
||||
uint16 mmu_sr;
|
||||
|
||||
const uint8* cyc_instruction;
|
||||
const uint8* cyc_exception;
|
||||
|
||||
|
|
@ -1011,6 +1023,8 @@ char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type);
|
|||
|
||||
/* ---------------------------- Read Immediate ---------------------------- */
|
||||
|
||||
#include "m68kmmu.h"
|
||||
|
||||
/* Handles all immediate reads, does address error check, function code setting,
|
||||
* and prefetching if they are enabled in m68kconf.h
|
||||
*/
|
||||
|
|
|
|||
28
m68kdasm.c
28
m68kdasm.c
|
|
@ -3019,6 +3019,32 @@ static void d68030_pmove(void)
|
|||
// do this after fetching the second PMOVE word so we properly get the 3rd if necessary
|
||||
str = get_ea_mode_str_32(g_cpu_ir);
|
||||
|
||||
if ((modes & 0xfde0) == 0x2000) // PLOAD
|
||||
{
|
||||
if (modes & 0x0200)
|
||||
{
|
||||
sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((modes & 0xe200) == 0x2000) // PFLUSHA
|
||||
{
|
||||
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]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((modes>>13) & 0x7)
|
||||
{
|
||||
case 0: // MC68030/040 form with FD bit
|
||||
|
|
@ -3767,7 +3793,7 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// f028 2215 0008
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
|
|
|
|||
21
m68kfpu.c
21
m68kfpu.c
|
|
@ -1,27 +1,6 @@
|
|||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "m68kcpu.h"
|
||||
|
||||
extern void exit(int);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define NORETURN __declspec(noreturn)
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
# define NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
# define NORETURN
|
||||
#endif
|
||||
|
||||
// TODO: Remove this and replace with a non-fatal signaling mechanism
|
||||
static NORETURN void fatalerror(char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
fprintf(stderr,format,ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define FPCC_N 0x08000000
|
||||
#define FPCC_Z 0x04000000
|
||||
#define FPCC_I 0x02000000
|
||||
|
|
|
|||
193
m68kmmu.h
Normal file
193
m68kmmu.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
m68kmmu.h - PMMU implementation for 68851/68030/68040
|
||||
|
||||
By R. Belmont
|
||||
|
||||
Copyright Nicola Salmoria and the MAME Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern void exit(int);
|
||||
|
||||
// TODO: Remove this and replace with a non-fatal signaling mechanism
|
||||
inline void fatalerror(char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
fprintf(stderr,format,ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
pmmu_translate_addr: perform 68851/68030-style PMMU address translation
|
||||
*/
|
||||
inline uint pmmu_translate_addr(uint addr_in)
|
||||
{
|
||||
uint addr_out, tbl_entry, tbl_entry2, tamode, tbmode;
|
||||
uint root_aptr, root_limit, tofs, is, abits, bbits; // , cbits;
|
||||
uint resolved, tptr, shift;
|
||||
|
||||
resolved = 0;
|
||||
addr_out = addr_in;
|
||||
|
||||
// if SRP is enabled and we're in supervisor mode, use it
|
||||
if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000))
|
||||
{
|
||||
root_aptr = m68ki_cpu.mmu_srp_aptr;
|
||||
root_limit = m68ki_cpu.mmu_srp_limit;
|
||||
}
|
||||
else // else use the CRP
|
||||
{
|
||||
root_aptr = m68ki_cpu.mmu_crp_aptr;
|
||||
root_limit = m68ki_cpu.mmu_crp_limit;
|
||||
}
|
||||
|
||||
// get initial shift (# of top bits to ignore)
|
||||
is = (m68ki_cpu.mmu_tc>>16) & 0xf;
|
||||
abits = (m68ki_cpu.mmu_tc>>12)&0xf;
|
||||
bbits = (m68ki_cpu.mmu_tc>>8)&0xf;
|
||||
// cbits = (m68ki_cpu.mmu_tc>>4)&0xf;
|
||||
|
||||
// fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
|
||||
|
||||
// get table A offset
|
||||
tofs = (addr_in<<is)>>(32-abits);
|
||||
|
||||
// find out what format table A is
|
||||
switch (root_limit & 3)
|
||||
{
|
||||
case 0: // invalid, should cause MMU exception
|
||||
case 1: // page descriptor, should cause direct mapping
|
||||
fatalerror("680x0 PMMU: Unhandled root mode\n");
|
||||
break;
|
||||
|
||||
case 2: // valid 4 byte descriptors
|
||||
tofs *= 4;
|
||||
// fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
||||
tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc));
|
||||
tamode = tbl_entry & 3;
|
||||
// fprintf(stderr,"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;
|
||||
// fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
|
||||
tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc));
|
||||
tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4);
|
||||
tamode = tbl_entry2 & 3;
|
||||
// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
|
||||
break;
|
||||
}
|
||||
|
||||
// get table B offset and pointer
|
||||
tofs = (addr_in<<(is+abits))>>(32-bbits);
|
||||
tptr = tbl_entry & 0xfffffff0;
|
||||
|
||||
// find out what format table B is, if any
|
||||
switch (tamode)
|
||||
{
|
||||
case 0: // invalid, should cause MMU exception
|
||||
fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in);
|
||||
break;
|
||||
|
||||
case 2: // 4-byte table B descriptor
|
||||
tofs *= 4;
|
||||
// fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr);
|
||||
tbl_entry = m68k_read_memory_32( tofs + tptr);
|
||||
tbmode = tbl_entry & 3;
|
||||
// fprintf(stderr,"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;
|
||||
// fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr);
|
||||
tbl_entry2 = m68k_read_memory_32( tofs + tptr);
|
||||
tbl_entry = m68k_read_memory_32( tofs + tptr + 4);
|
||||
tbmode = tbl_entry2 & 3;
|
||||
// fprintf(stderr,"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
|
||||
tbl_entry &= 0xffffff00;
|
||||
|
||||
shift = is+abits;
|
||||
addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
|
||||
resolved = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// if table A wasn't early-out, continue to process table B
|
||||
if (!resolved)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
|
||||
case 1: // early termination descriptor
|
||||
tbl_entry &= 0xffffff00;
|
||||
|
||||
shift = is+abits+bbits;
|
||||
addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
|
||||
resolved = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if ((addr_in < 0x40000000) || (addr_in > 0x4fffffff)) printf("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
|
||||
|
||||
*/
|
||||
|
||||
Loading…
Reference in a new issue