M680x0 updates [Hans Ostermeyer]

- Instruction cache emulated on '020 and later
- Fixed interaction between MMU and bfextu/bfexts/bfins
- Added fsgldiv, fsglmul, and fscc FPU instructions
- Fixed fault address in stack frame
- Fixed supervisor violation bit in MMU status register
- Add fmovem modes 1 and 3
- Various other MMU fixes
This commit is contained in:
R. Belmont 2011-02-21 21:40:58 +00:00
parent 18aca550f0
commit 1fcc151bc9
5 changed files with 221 additions and 75 deletions

View File

@ -2634,17 +2634,20 @@ M68KMAKE_OP(bfexts, 32, ., .)
if(BIT_5(word2)) if(BIT_5(word2))
width = REG_D[width&7]; width = REG_D[width&7];
/* Offset is signed so we have to use ugly math =( */ if(BIT_B(word2))
ea += offset / 8;
offset %= 8;
if(offset < 0)
{ {
offset += 8; /* Offset is signed so we have to use ugly math =( */
ea--; ea += offset / 8;
offset %= 8;
if(offset < 0)
{
offset += 8;
ea--;
}
} }
width = ((width-1) & 31) + 1; width = ((width-1) & 31) + 1;
data = m68ki_read_32(m68k, ea); data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
data = MASK_OUT_ABOVE_32(data<<offset); data = MASK_OUT_ABOVE_32(data<<offset);
@ -2716,17 +2719,20 @@ M68KMAKE_OP(bfextu, 32, ., .)
if(BIT_5(word2)) if(BIT_5(word2))
width = REG_D[width&7]; width = REG_D[width&7];
/* Offset is signed so we have to use ugly math =( */ if(BIT_B(word2))
ea += offset / 8;
offset %= 8;
if(offset < 0)
{ {
offset += 8; /* Offset is signed so we have to use ugly math =( */
ea--; ea += offset / 8;
offset %= 8;
if(offset < 0)
{
offset += 8;
ea--;
}
} }
width = ((width-1) & 31) + 1; width = ((width-1) & 31) + 1;
data = m68ki_read_32(m68k, ea); data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
data = MASK_OUT_ABOVE_32(data<<offset); data = MASK_OUT_ABOVE_32(data<<offset);
if((offset+width) > 32) if((offset+width) > 32)
@ -2813,7 +2819,7 @@ M68KMAKE_OP(bfffo, 32, ., .)
} }
width = ((width-1) & 31) + 1; width = ((width-1) & 31) + 1;
data = m68ki_read_32(m68k, ea); data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
data = MASK_OUT_ABOVE_32(data<<local_offset); data = MASK_OUT_ABOVE_32(data<<local_offset);
if((local_offset+width) > 32) if((local_offset+width) > 32)
@ -2902,13 +2908,16 @@ M68KMAKE_OP(bfins, 32, ., .)
if(BIT_5(word2)) if(BIT_5(word2))
width = REG_D[width&7]; width = REG_D[width&7];
/* Offset is signed so we have to use ugly math =( */ if(BIT_B(word2))
ea += offset / 8;
offset %= 8;
if(offset < 0)
{ {
offset += 8; /* Offset is signed so we have to use ugly math =( */
ea--; ea += offset / 8;
offset %= 8;
if(offset < 0)
{
offset += 8;
ea--;
}
} }
width = ((width-1) & 31) + 1; width = ((width-1) & 31) + 1;
@ -2920,11 +2929,18 @@ M68KMAKE_OP(bfins, 32, ., .)
m68k->not_z_flag = insert_base; m68k->not_z_flag = insert_base;
insert_long = insert_base >> offset; insert_long = insert_base >> offset;
data_long = m68ki_read_32(m68k, ea); data_long = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
m68k->v_flag = VFLAG_CLEAR; m68k->v_flag = VFLAG_CLEAR;
m68k->c_flag = CFLAG_CLEAR; m68k->c_flag = CFLAG_CLEAR;
m68ki_write_32(m68k, ea, (data_long & ~mask_long) | insert_long); if((width + offset) < 16)
{
m68ki_write_16(m68k, ea, ((data_long & ~mask_long) | insert_long) >> 16);
}
else
{
m68ki_write_32(m68k, ea, (data_long & ~mask_long) | insert_long);
}
if((width + offset) > 32) if((width + offset) > 32)
{ {
@ -6684,6 +6700,12 @@ M68KMAKE_OP(movec, 32, rc, .)
{ {
m68k->cacr = REG_DA[(word2 >> 12) & 15] & 0x0f; m68k->cacr = REG_DA[(word2 >> 12) & 15] & 0x0f;
} }
// logerror("movec to cacr=%04x\n", m68k->cacr);
if (m68k->cacr & (M68K_CACR_CI | M68K_CACR_CEI))
{
m68ki_ic_clear(m68k);
}
return; return;
} }
m68ki_exception_illegal(m68k); m68ki_exception_illegal(m68k);

View File

@ -632,9 +632,9 @@ static CPU_EXECUTE( m68k )
/* Call external hook to peek at CPU */ /* Call external hook to peek at CPU */
debugger_instruction_hook(device, REG_PC); debugger_instruction_hook(device, REG_PC);
// FIXME: remove this /* call external instruction hook (independent of debug mode) */
// void apollo_debug_instruction(device_t *device); if (m68k->instruction_hook != NULL)
// apollo_debug_instruction(device); m68k->instruction_hook(device, REG_PC);
/* Record previous program counter */ /* Record previous program counter */
REG_PPC = REG_PC; REG_PPC = REG_PC;
@ -672,13 +672,6 @@ static CPU_EXECUTE( m68k )
{ {
UINT32 sr; UINT32 sr;
// const char * disassemble(m68ki_cpu_core *m68k, offs_t pc);
// logerror(
// "PMMU: pc=%08x sp=%08x va=%08x bus error: %s\n",
// REG_PPC, REG_A[7], m68k->mmu_tmp_buserror_address,
// (m68k->mmu_tmp_buserror_address == REG_PPC) ? "-"
// : disassemble(m68k, REG_PPC));
m68k->mmu_tmp_buserror_occurred = 0; m68k->mmu_tmp_buserror_occurred = 0;
// restore cpu address registers to value at start of instruction // restore cpu address registers to value at start of instruction
@ -821,6 +814,15 @@ static CPU_RESET( m68k )
/* flush the MMU's cache */ /* flush the MMU's cache */
pmmu_atc_flush(m68k); pmmu_atc_flush(m68k);
if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
{
// clear instruction cache
m68ki_ic_clear(m68k);
}
// disable instruction hook
m68k->instruction_hook = NULL;
} }
static CPU_DISASSEMBLE( m68k ) static CPU_DISASSEMBLE( m68k )

View File

@ -103,6 +103,15 @@ typedef struct _m68ki_cpu_core m68ki_cpu_core;
/* MMU constants */ /* MMU constants */
#define MMU_ATC_ENTRIES (22) // 68851 has 64, 030 has 22 #define MMU_ATC_ENTRIES (22) // 68851 has 64, 030 has 22
/* instruction cache constants */
#define M68K_IC_SIZE 128
#define M68K_CACR_IBE 0x10 // Instruction Burst Enable
#define M68K_CACR_CI 0x08 // Clear Instruction Cache
#define M68K_CACR_CEI 0x04 // Clear Entry in Instruction Cache
#define M68K_CACR_FI 0x02 // Freeze Instruction Cache
#define M68K_CACR_EI 0x01 // Enable Instruction Cache
/* ======================================================================== */ /* ======================================================================== */
/* ================================ MACROS ================================ */ /* ================================ MACROS ================================ */
/* ======================================================================== */ /* ======================================================================== */
@ -706,6 +715,13 @@ struct _m68ki_cpu_core
UINT16 mmu_tmp_rw; /* temporary hack: read/write (1/0) for the mmu */ UINT16 mmu_tmp_rw; /* temporary hack: read/write (1/0) for the mmu */
UINT32 mmu_tmp_buserror_address; /* temporary hack: (first) bus error address */ UINT32 mmu_tmp_buserror_address; /* temporary hack: (first) bus error address */
UINT16 mmu_tmp_buserror_occurred; /* temporary hack: flag that bus error has occurred from mmu */ UINT16 mmu_tmp_buserror_occurred; /* temporary hack: flag that bus error has occurred from mmu */
UINT32 ic_address[M68K_IC_SIZE]; /* instruction cache address data */
UINT16 ic_data[M68K_IC_SIZE]; /* instruction cache content data */
/* external instruction hook (does not depend on debug mode) */
typedef int (*instruction_hook_t)(device_t *device, offs_t curpc);
instruction_hook_t instruction_hook;
}; };
@ -882,6 +898,43 @@ INLINE void m68kx_write_memory_32_pd(m68ki_cpu_core *m68k, unsigned int address,
/* ---------------------------- Read Immediate ---------------------------- */ /* ---------------------------- Read Immediate ---------------------------- */
// clear the instruction cache
INLINE void m68ki_ic_clear(m68ki_cpu_core *m68k)
{
int i;
for (i=0; i< M68K_IC_SIZE; i++) {
m68k->ic_address[i] = ~0;
}
}
// read immediate word using the instruction cache
INLINE UINT32 m68ki_ic_readimm16(m68ki_cpu_core *m68k, UINT32 address)
{
if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type) && (m68k->cacr & M68K_CACR_EI))
{
UINT32 ic_offset = (address >> 1) % M68K_IC_SIZE;
if (m68k->ic_address[ic_offset] == address)
{
return m68k->ic_data[ic_offset];
}
else
{
UINT32 data = m68k->memory.readimm16(address);
if (!m68k->mmu_tmp_buserror_occurred)
{
m68k->ic_data[ic_offset] = data;
m68k->ic_address[ic_offset] = address;
}
return data;
}
}
else
{
return m68k->memory.readimm16(address);
}
}
/* Handles all immediate reads, does address error check, function code setting, /* Handles all immediate reads, does address error check, function code setting,
* and prefetching if they are enabled in m68kconf.h * and prefetching if they are enabled in m68kconf.h
*/ */
@ -896,14 +949,14 @@ INLINE UINT32 m68ki_read_imm_16(m68ki_cpu_core *m68k)
if(REG_PC != m68k->pref_addr) if(REG_PC != m68k->pref_addr)
{ {
m68k->pref_data = m68k->memory.readimm16(REG_PC); m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC; m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
} }
result = MASK_OUT_ABOVE_16(m68k->pref_data); result = MASK_OUT_ABOVE_16(m68k->pref_data);
REG_PC += 2; REG_PC += 2;
if (!m68k->mmu_tmp_buserror_occurred) { if (!m68k->mmu_tmp_buserror_occurred) {
// prefetch only if no bus error occurred in opcode fetch // prefetch only if no bus error occurred in opcode fetch
m68k->pref_data = m68k->memory.readimm16(REG_PC); m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC; m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
// ignore bus error on prefetch // ignore bus error on prefetch
m68k->mmu_tmp_buserror_occurred = 0; m68k->mmu_tmp_buserror_occurred = 0;
@ -924,16 +977,16 @@ INLINE UINT32 m68ki_read_imm_32(m68ki_cpu_core *m68k)
if(REG_PC != m68k->pref_addr) if(REG_PC != m68k->pref_addr)
{ {
m68k->pref_addr = REG_PC; m68k->pref_addr = REG_PC;
m68k->pref_data = m68k->memory.readimm16(m68k->pref_addr); m68k->pref_data = m68ki_ic_readimm16(m68k, m68k->pref_addr);
} }
temp_val = MASK_OUT_ABOVE_16(m68k->pref_data); temp_val = MASK_OUT_ABOVE_16(m68k->pref_data);
REG_PC += 2; REG_PC += 2;
m68k->pref_addr = REG_PC; m68k->pref_addr = REG_PC;
m68k->pref_data = m68k->memory.readimm16(m68k->pref_addr); m68k->pref_data = m68ki_ic_readimm16(m68k, m68k->pref_addr);
temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(m68k->pref_data)); temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(m68k->pref_data));
REG_PC += 2; REG_PC += 2;
m68k->pref_data = m68k->memory.readimm16(REG_PC); m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC; m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
return temp_val; return temp_val;
@ -1543,7 +1596,9 @@ void m68ki_stack_frame_1010(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);
/* SPECIAL STATUS REGISTER */ /* SPECIAL STATUS REGISTER */
m68ki_push_16(m68k, 0); // set bit for: Rerun Faulted bus Cycle, or run pending prefetch
// set FC
m68ki_push_16(m68k, 0x0100 | m68k->mmu_tmp_fc );
/* INTERNAL REGISTER */ /* INTERNAL REGISTER */
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);
@ -1590,7 +1645,7 @@ void m68ki_stack_frame_1011(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT
m68ki_push_32(m68k, 0); m68ki_push_32(m68k, 0);
/* STAGE B ADDRESS (2 words) */ /* STAGE B ADDRESS (2 words) */
m68ki_push_32(m68k, fault_address); m68ki_push_32(m68k, 0);
/* INTERNAL REGISTER (4 words) */ /* INTERNAL REGISTER (4 words) */
m68ki_push_32(m68k, 0); m68ki_push_32(m68k, 0);
@ -1606,7 +1661,7 @@ void m68ki_stack_frame_1011(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);
/* DATA CYCLE FAULT ADDRESS (2 words) */ /* DATA CYCLE FAULT ADDRESS (2 words) */
m68ki_push_32(m68k, 0); m68ki_push_32(m68k, fault_address);
/* INSTRUCTION PIPE STAGE B */ /* INSTRUCTION PIPE STAGE B */
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);
@ -1615,7 +1670,7 @@ void m68ki_stack_frame_1011(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);
/* SPECIAL STATUS REGISTER */ /* SPECIAL STATUS REGISTER */
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0x0100 | m68k->mmu_tmp_fc);
/* INTERNAL REGISTER */ /* INTERNAL REGISTER */
m68ki_push_16(m68k, 0); m68ki_push_16(m68k, 0);

View File

@ -1318,6 +1318,11 @@ static void fpgen_rm_reg(m68ki_cpu_core *m68k, UINT16 w2)
m68k->remaining_cycles -= 109; m68k->remaining_cycles -= 109;
break; break;
} }
// case 0x0e: // FSIN
// {
// // TODO
// break;
// }
case 0x18: // FABS case 0x18: // FABS
{ {
REG_FP[dst] = source; REG_FP[dst] = source;
@ -1365,6 +1370,12 @@ static void fpgen_rm_reg(m68ki_cpu_core *m68k, UINT16 w2)
m68k->remaining_cycles -= 11; m68k->remaining_cycles -= 11;
break; break;
} }
case 0x24: // FSGLDIV
{
REG_FP[dst] = floatx80_div(REG_FP[dst], source);
m68k->remaining_cycles -= 43; // // ? (value is from FDIV)
break;
}
case 0x25: // FREM case 0x25: // FREM
{ {
REG_FP[dst] = floatx80_rem(REG_FP[dst], source); REG_FP[dst] = floatx80_rem(REG_FP[dst], source);
@ -1372,6 +1383,13 @@ static void fpgen_rm_reg(m68ki_cpu_core *m68k, UINT16 w2)
m68k->remaining_cycles -= 43; // guess m68k->remaining_cycles -= 43; // guess
break; break;
} }
case 0x27: // FSGLMUL
{
REG_FP[dst] = floatx80_mul(REG_FP[dst], source);
SET_CONDITION_CODES(m68k, REG_FP[dst]);
m68k->remaining_cycles -= 11; // ? (value is from FMUL)
break;
}
case 0x28: // FSUB case 0x28: // FSUB
{ {
REG_FP[dst] = floatx80_sub(REG_FP[dst], source); REG_FP[dst] = floatx80_sub(REG_FP[dst], source);
@ -1396,7 +1414,7 @@ static void fpgen_rm_reg(m68ki_cpu_core *m68k, UINT16 w2)
break; break;
} }
default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4); default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PPC);
} }
} }
@ -1507,6 +1525,10 @@ static void fmovem(m68ki_cpu_core *m68k, UINT16 w2)
{ {
switch (mode) switch (mode)
{ {
case 1: // Dynamic register list, postincrement or control addressing mode.
// FIXME: not really tested, but seems to work
reglist = REG_D[(reglist >> 4) & 7];
case 0: // Static register list, predecrement or control addressing mode case 0: // Static register list, predecrement or control addressing mode
{ {
for (i=0; i < 8; i++) for (i=0; i < 8; i++)
@ -1531,13 +1553,41 @@ static void fmovem(m68ki_cpu_core *m68k, UINT16 w2)
break; break;
} }
default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); case 2: // Static register list, postdecrement or control addressing mode
{
for (i=0; i < 8; i++)
{
if (reglist & (1 << i))
{
switch (ea >> 3)
{
case 5: // (d16, An)
case 6: // (An) + (Xn) + d8
store_extended_float80(m68k, mem_addr, REG_FP[7-i]);
mem_addr += 12;
break;
default:
WRITE_EA_FPE(m68k, ea, REG_FP[7-i]);
break;
}
m68k->remaining_cycles -= 2;
}
}
break;
}
default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
} }
} }
else // From mem to FP regs else // From mem to FP regs
{ {
switch (mode) switch (mode)
{ {
case 3: // Dynamic register list, predecrement addressing mode.
// FIXME: not really tested, but seems to work
reglist = REG_D[(reglist >> 4) & 7];
case 2: // Static register list, postincrement or control addressing mode case 2: // Static register list, postincrement or control addressing mode
{ {
for (i=0; i < 8; i++) for (i=0; i < 8; i++)
@ -1561,11 +1611,20 @@ static void fmovem(m68ki_cpu_core *m68k, UINT16 w2)
break; break;
} }
default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
} }
} }
} }
static void fscc(m68ki_cpu_core *m68k)
{
int ea = m68k->ir & 0x3f;
int condition = (INT16)(OPER_I_16(m68k));
WRITE_EA_8(m68k, ea, TEST_CONDITION(m68k, condition) ? 0xff : 0);
m68k->remaining_cycles -= 7; // ???
}
static void fbcc16(m68ki_cpu_core *m68k) static void fbcc16(m68ki_cpu_core *m68k)
{ {
INT32 offset; INT32 offset;
@ -1646,15 +1705,15 @@ void m68040_fpu_op0(m68ki_cpu_core *m68k)
case 1: // FBcc disp16 case 1: // FBcc disp16
{ {
switch ((m68k->ir >> 3) & 0x3) { switch ((m68k->ir >> 3) & 0x7) {
case 1: // FDBcc case 1: // FDBcc
// TODO: // TODO:
break; break;
default: // FScc (?) default: // FScc (?)
// TODO: fscc(m68k);
break; return;
} }
fatalerror("M68kFPU: unimplemented main op %d with mode %d\n", (m68k->ir >> 6) & 0x3, (m68k->ir >> 3) & 0x7); fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (m68k->ir >> 6) & 0x3, (m68k->ir >> 3) & 0x7, REG_PPC);
} }
case 2: // FBcc disp16 case 2: // FBcc disp16

View File

@ -199,13 +199,13 @@ INLINE UINT32 get_dt2_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
return tbl_entry; return tbl_entry;
} }
INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest) INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, UINT8 ptest)
{ {
UINT32 tbl_entry2 = m68k->program->read_dword(tptr); UINT32 tbl_entry2 = m68k->program->read_dword(tptr);
UINT32 tbl_entry = m68k->program->read_dword(tptr + 4); UINT32 tbl_entry = m68k->program->read_dword(tptr + 4);
UINT32 dt = tbl_entry2 & M68K_MMU_DF_DT; UINT32 dt = tbl_entry2 & M68K_MMU_DF_DT;
m68k->mmu_tmp_sr |= tbl_entry2 & 0x0100 ? M68K_MMU_SR_SUPERVISOR_ONLY : 0; m68k->mmu_tmp_sr |= ((tbl_entry2 & 0x0100) && !(fc & 4)) ? M68K_MMU_SR_SUPERVISOR_ONLY : 0;
m68k->mmu_tmp_sr |= tbl_entry2 & 0x0004 ? M68K_MMU_SR_WRITE_PROTECT : 0; m68k->mmu_tmp_sr |= tbl_entry2 & 0x0004 ? M68K_MMU_SR_WRITE_PROTECT : 0;
if (!ptest) if (!ptest)
@ -272,27 +272,35 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
// first see if this is already in the ATC // first see if this is already in the ATC
for (i = 0; i < MMU_ATC_ENTRIES; i++) for (i = 0; i < MMU_ATC_ENTRIES; i++)
{ {
// if tag bits and function code match, we've got it if (m68k->mmu_atc_tag[i] != atc_tag)
if (m68k->mmu_atc_tag[i] == atc_tag)
{ {
if (m68k->mmu_tmp_rw || !(m68k->mmu_atc_data[i] & M68K_MMU_ATC_WRITE_PR)) // tag bits and function code don't match
{ }
// read access or write access and not write protected else if (!m68k->mmu_tmp_rw && (m68k->mmu_atc_data[i] & M68K_MMU_ATC_WRITE_PR))
if (!m68k->mmu_tmp_rw && !ptest) {
{ // write mode, but write protected
// FIXME: must set modified in PMMU tables as well }
m68k->mmu_atc_data[i] |= M68K_MMU_ATC_MODIFIED; else if (!m68k->mmu_tmp_rw && !(m68k->mmu_atc_data[i] & M68K_MMU_ATC_MODIFIED))
} {
else // first write; must set modified in PMMU tables as well
{ }
// FIXME: supervisor mode? else
m68k->mmu_tmp_sr = M68K_MMU_SR_MODIFIED; {
} // read access or write access and not write protected
addr_out = (m68k->mmu_atc_data[i]<<8) | (addr_in & ~(~0 << ps)); if (!m68k->mmu_tmp_rw && !ptest)
// logerror("ATC[%2d] hit: log %08x -> phys %08x pc=%08x fc=%d\n", i, addr_in, addr_out, REG_PPC, fc); {
// pmmu_atc_count++; // FIXME: must set modified in PMMU tables as well
return addr_out; m68k->mmu_atc_data[i] |= M68K_MMU_ATC_MODIFIED;
} }
else
{
// FIXME: supervisor mode?
m68k->mmu_tmp_sr = M68K_MMU_SR_MODIFIED;
}
addr_out = (m68k->mmu_atc_data[i] << 8) | (addr_in & ~(~0 << ps));
// logerror("ATC[%2d] hit: log %08x -> phys %08x pc=%08x fc=%d\n", i, addr_in, addr_out, REG_PPC, fc);
// pmmu_atc_count++;
return addr_out;
} }
} }
@ -344,7 +352,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
case M68K_MMU_DF_DT3: // valid 8 byte descriptors case M68K_MMU_DF_DT3: // valid 8 byte descriptors
tofs *= 8; tofs *= 8;
// if (verbose) logerror("PMMU: reading table A entries at %08x\n", tofs + tptr); // if (verbose) logerror("PMMU: reading table A entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tofs + tptr, ptest); tbl_entry = get_dt3_table_entry(m68k, tofs + tptr, fc, ptest);
tamode = tbl_entry & M68K_MMU_DF_DT; tamode = tbl_entry & M68K_MMU_DF_DT;
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); // if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
break; break;
@ -377,7 +385,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
case M68K_MMU_DF_DT3: // 8-byte table B descriptor case M68K_MMU_DF_DT3: // 8-byte table B descriptor
tofs *= 8; tofs *= 8;
// if (verbose) logerror("PMMU: reading table B entries at %08x\n", tofs + tptr); // if (verbose) logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tptr + tofs, ptest); tbl_entry = get_dt3_table_entry(m68k, tptr + tofs, fc, ptest);
tbmode = tbl_entry & M68K_MMU_DF_DT; tbmode = tbl_entry & M68K_MMU_DF_DT;
tbl_entry &= ~M68K_MMU_DF_DT; tbl_entry &= ~M68K_MMU_DF_DT;
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); // if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
@ -421,7 +429,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
case M68K_MMU_DF_DT3: // 8-byte table C descriptor case M68K_MMU_DF_DT3: // 8-byte table C descriptor
tofs *= 8; tofs *= 8;
// if (verbose) logerror("PMMU: reading table C entries at %08x\n", tofs + tptr); // if (verbose) logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
tbl_entry = get_dt3_table_entry(m68k, tptr+ tofs, ptest); tbl_entry = get_dt3_table_entry(m68k, tptr+ tofs, fc, ptest);
tcmode = tbl_entry & M68K_MMU_DF_DT; tcmode = tbl_entry & M68K_MMU_DF_DT;
// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tcmode, tofs); // if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tcmode, tofs);
break; break;
@ -470,7 +478,7 @@ INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest
m68k->mmu_tmp_buserror_address = addr_in; m68k->mmu_tmp_buserror_address = addr_in;
} }
} }
else if ((m68k->mmu_tmp_sr & M68K_MMU_SR_SUPERVISOR_ONLY) && !(fc & 4)) else if (m68k->mmu_tmp_sr & M68K_MMU_SR_SUPERVISOR_ONLY)
{ {
if (++m68k->mmu_tmp_buserror_occurred == 1) if (++m68k->mmu_tmp_buserror_occurred == 1)
{ {