Cog/Frameworks/lazyusf2/lazyusf2/r4300/interpreter_tlb.def

250 lines
10 KiB
Modula-2

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - interpreter_tlb.def *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2002 Hacktarux *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <zlib.h> // For adler32()
DECLARE_INSTRUCTION(TLBR)
{
int index;
index = state->g_cp0_regs[CP0_INDEX_REG] & 0x1F;
state->g_cp0_regs[CP0_PAGEMASK_REG] = state->tlb_e[index].mask << 13;
state->g_cp0_regs[CP0_ENTRYHI_REG] = ((state->tlb_e[index].vpn2 << 13) | state->tlb_e[index].asid);
state->g_cp0_regs[CP0_ENTRYLO0_REG] = (state->tlb_e[index].pfn_even << 6) | (state->tlb_e[index].c_even << 3)
| (state->tlb_e[index].d_even << 2) | (state->tlb_e[index].v_even << 1)
| state->tlb_e[index].g;
state->g_cp0_regs[CP0_ENTRYLO1_REG] = (state->tlb_e[index].pfn_odd << 6) | (state->tlb_e[index].c_odd << 3)
| (state->tlb_e[index].d_odd << 2) | (state->tlb_e[index].v_odd << 1)
| state->tlb_e[index].g;
ADD_TO_PC(1);
}
static void TLBWrite(usf_state_t * state, unsigned int idx)
{
if (state->r4300emu != CORE_PURE_INTERPRETER)
{
unsigned int i;
if (state->tlb_e[idx].v_even)
{
for (i=state->tlb_e[idx].start_even>>12; i<=state->tlb_e[idx].end_even>>12; i++)
{
if(!state->invalid_code[i] &&(state->invalid_code[state->tlb_LUT_r[i]>>12] ||
state->invalid_code[(state->tlb_LUT_r[i]>>12)+0x20000]))
state->invalid_code[i] = 1;
if (!state->invalid_code[i])
{
/*int j;
md5_state_t state;
md5_byte_t digest[16];
md5_init(&state);
md5_append(&state,
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
0x1000);
md5_finish(&state, digest);
for (j=0; j<16; j++) state->blocks[i]->md5[j] = digest[j];*/
state->blocks[i]->adler32 = (unsigned int) adler32(0, (const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4], 0x1000);
state->invalid_code[i] = 1;
}
else if (state->blocks[i])
{
/*int j;
for (j=0; j<16; j++) state->blocks[i]->md5[j] = 0;*/
state->blocks[i]->adler32 = 0;
}
}
}
if (state->tlb_e[idx].v_odd)
{
for (i=state->tlb_e[idx].start_odd>>12; i<=state->tlb_e[idx].end_odd>>12; i++)
{
if(!state->invalid_code[i] &&(state->invalid_code[state->tlb_LUT_r[i]>>12] ||
state->invalid_code[(state->tlb_LUT_r[i]>>12)+0x20000]))
state->invalid_code[i] = 1;
if (!state->invalid_code[i])
{
/*int j;
md5_state_t state;
md5_byte_t digest[16];
md5_init(&state);
md5_append(&state,
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
0x1000);
md5_finish(&state, digest);
for (j=0; j<16; j++) state->blocks[i]->md5[j] = digest[j];*/
state->blocks[i]->adler32 = (unsigned int) adler32(0, (const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4], 0x1000);
state->invalid_code[i] = 1;
}
else if (state->blocks[i])
{
/*int j;
for (j=0; j<16; j++) state->blocks[i]->md5[j] = 0;*/
state->blocks[i]->adler32 = 0;
}
}
}
}
tlb_unmap(state, &state->tlb_e[idx]);
state->tlb_e[idx].g = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & state->g_cp0_regs[CP0_ENTRYLO1_REG] & 1);
state->tlb_e[idx].pfn_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x3FFFFFC0) >> 6;
state->tlb_e[idx].pfn_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x3FFFFFC0) >> 6;
state->tlb_e[idx].c_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x38) >> 3;
state->tlb_e[idx].c_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x38) >> 3;
state->tlb_e[idx].d_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x4) >> 2;
state->tlb_e[idx].d_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x4) >> 2;
state->tlb_e[idx].v_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x2) >> 1;
state->tlb_e[idx].v_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x2) >> 1;
state->tlb_e[idx].asid = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFF);
state->tlb_e[idx].vpn2 = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFFFFE000) >> 13;
//state->tlb_e[idx].r = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xC000000000000000LL) >> 62;
state->tlb_e[idx].mask = (state->g_cp0_regs[CP0_PAGEMASK_REG] & 0x1FFE000) >> 13;
state->tlb_e[idx].start_even = state->tlb_e[idx].vpn2 << 13;
state->tlb_e[idx].end_even = state->tlb_e[idx].start_even+
(state->tlb_e[idx].mask << 12) + 0xFFF;
state->tlb_e[idx].phys_even = state->tlb_e[idx].pfn_even << 12;
state->tlb_e[idx].start_odd = state->tlb_e[idx].end_even+1;
state->tlb_e[idx].end_odd = state->tlb_e[idx].start_odd+
(state->tlb_e[idx].mask << 12) + 0xFFF;
state->tlb_e[idx].phys_odd = state->tlb_e[idx].pfn_odd << 12;
tlb_map(state, &state->tlb_e[idx]);
if (state->r4300emu != CORE_PURE_INTERPRETER)
{
unsigned int i;
if (state->tlb_e[idx].v_even)
{
for (i=state->tlb_e[idx].start_even>>12; i<=state->tlb_e[idx].end_even>>12; i++)
{
/*if (state->blocks[i] && (state->blocks[i]->md5[0] || state->blocks[i]->md5[1] ||
state->blocks[i]->md5[2] || state->blocks[i]->md5[3]))
{
int j;
int equal = 1;
md5_state_t state;
md5_byte_t digest[16];
md5_init(&state);
md5_append(&state,
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
0x1000);
md5_finish(&state, digest);
for (j=0; j<16; j++)
if (digest[j] != state->blocks[i]->md5[j])
equal = 0;
if (equal) state->invalid_code[i] = 0;
}*/
if(state->blocks[i] && state->blocks[i]->adler32)
{
if(state->blocks[i]->adler32 == adler32(0,(const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],0x1000))
state->invalid_code[i] = 0;
}
}
}
if (state->tlb_e[idx].v_odd)
{
for (i=state->tlb_e[idx].start_odd>>12; i<=state->tlb_e[idx].end_odd>>12; i++)
{
/*if (state->blocks[i] && (state->blocks[i]->md5[0] || state->blocks[i]->md5[1] ||
state->blocks[i]->md5[2] || state->blocks[i]->md5[3]))
{
int j;
int equal = 1;
md5_state_t state;
md5_byte_t digest[16];
md5_init(&state);
md5_append(&state,
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
0x1000);
md5_finish(&state, digest);
for (j=0; j<16; j++)
if (digest[j] != state->blocks[i]->md5[j])
equal = 0;
if (equal) state->invalid_code[i] = 0;
}*/
if(state->blocks[i] && state->blocks[i]->adler32)
{
if(state->blocks[i]->adler32 == adler32(0,(const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],0x1000))
state->invalid_code[i] = 0;
}
}
}
}
}
DECLARE_INSTRUCTION(TLBWI)
{
TLBWrite(state, state->g_cp0_regs[CP0_INDEX_REG]&0x3F);
ADD_TO_PC(1);
}
DECLARE_INSTRUCTION(TLBWR)
{
update_count(state);
state->g_cp0_regs[CP0_RANDOM_REG] = (state->g_cp0_regs[CP0_COUNT_REG]/2 % (32 - state->g_cp0_regs[CP0_WIRED_REG]))
+ state->g_cp0_regs[CP0_WIRED_REG];
TLBWrite(state, state->g_cp0_regs[CP0_RANDOM_REG]);
ADD_TO_PC(1);
}
DECLARE_INSTRUCTION(TLBP)
{
int i;
state->g_cp0_regs[CP0_INDEX_REG] |= 0x80000000;
for (i=0; i<32; i++)
{
if (((state->tlb_e[i].vpn2 & (~state->tlb_e[i].mask)) ==
(((state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFFFFE000) >> 13) & (~state->tlb_e[i].mask))) &&
((state->tlb_e[i].g) ||
(state->tlb_e[i].asid == (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFF))))
{
state->g_cp0_regs[CP0_INDEX_REG] = i;
break;
}
}
ADD_TO_PC(1);
}
DECLARE_INSTRUCTION(ERET)
{
update_count(state);
if (state->g_cp0_regs[CP0_STATUS_REG] & 0x4)
{
DebugMessage(state, M64MSG_ERROR, "error in ERET");
state->stop=1;
}
else
{
state->g_cp0_regs[CP0_STATUS_REG] &= ~0x2;
generic_jump_to(state, state->g_cp0_regs[CP0_EPC_REG]);
}
state->llbit = 0;
check_interupt(state);
state->last_addr = PCADDR;
if (state->cycle_count >= 0) gen_interupt(state);
}