800 lines
22 KiB
Modula-2
800 lines
22 KiB
Modula-2
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Mupen64plus - interpreter_r4300.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. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
DECLARE_JUMP(J, (jinst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &state->reg[0], 0, 0)
|
|
DECLARE_JUMP(JAL, (jinst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &state->reg[31], 0, 0)
|
|
DECLARE_JUMP(BEQ, PCADDR + (iimmediate+1)*4, irs == irt, &state->reg[0], 0, 0)
|
|
DECLARE_JUMP(BNE, PCADDR + (iimmediate+1)*4, irs != irt, &state->reg[0], 0, 0)
|
|
DECLARE_JUMP(BLEZ, PCADDR + (iimmediate+1)*4, irs <= 0, &state->reg[0], 0, 0)
|
|
DECLARE_JUMP(BGTZ, PCADDR + (iimmediate+1)*4, irs > 0, &state->reg[0], 0, 0)
|
|
|
|
DECLARE_INSTRUCTION(ADDI)
|
|
{
|
|
irt32 = irs32 + iimmediate;
|
|
sign_extended(irt);
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(ADDIU)
|
|
{
|
|
irt32 = irs32 + iimmediate;
|
|
sign_extended(irt);
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SLTI)
|
|
{
|
|
if (irs < iimmediate) irt = 1;
|
|
else irt = 0;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SLTIU)
|
|
{
|
|
if ((unsigned long long)irs < (unsigned long long)((long long)iimmediate))
|
|
irt = 1;
|
|
else irt = 0;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(ANDI)
|
|
{
|
|
irt = irs & (unsigned short)iimmediate;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(ORI)
|
|
{
|
|
irt = irs | (unsigned short)iimmediate;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(XORI)
|
|
{
|
|
irt = irs ^ (unsigned short)iimmediate;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LUI)
|
|
{
|
|
irt32 = iimmediate << 16;
|
|
sign_extended(irt);
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_JUMP(BEQL, PCADDR + (iimmediate+1)*4, irs == irt, &state->reg[0], 1, 0)
|
|
DECLARE_JUMP(BNEL, PCADDR + (iimmediate+1)*4, irs != irt, &state->reg[0], 1, 0)
|
|
DECLARE_JUMP(BLEZL, PCADDR + (iimmediate+1)*4, irs <= 0, &state->reg[0], 1, 0)
|
|
DECLARE_JUMP(BGTZL, PCADDR + (iimmediate+1)*4, irs > 0, &state->reg[0], 1, 0)
|
|
|
|
DECLARE_INSTRUCTION(DADDI)
|
|
{
|
|
irt = irs + iimmediate;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(DADDIU)
|
|
{
|
|
irt = irs + iimmediate;
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
// TODOXXX refactor the following functions to remove the
|
|
// lsaddr and lsrpt locals. this may lead to a small speedup too
|
|
|
|
DECLARE_INSTRUCTION(LDL)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 7)
|
|
{
|
|
case 0:
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_dword_in_memory();
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFF) | (word << 8);
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
|
|
break;
|
|
case 4:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFF) | (word << 32);
|
|
break;
|
|
case 5:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFLL) | (word << 40);
|
|
break;
|
|
case 6:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFLL) | (word << 48);
|
|
break;
|
|
case 7:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFFLL) | (word << 56);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LDR)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 7)
|
|
{
|
|
case 0:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | (word >> 56);
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | (word >> 48);
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | (word >> 40);
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFF00000000LL) | (word >> 32);
|
|
break;
|
|
case 4:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFF0000000000LL) | (word >> 24);
|
|
break;
|
|
case 5:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFF000000000000LL) | (word >> 16);
|
|
break;
|
|
case 6:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFF00000000000000LL) | (word >> 8);
|
|
break;
|
|
case 7:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_dword_in_memory();
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LB)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_byte_in_memory();
|
|
if (state->address)
|
|
sign_extendedb(*lsrtp);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LH)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_hword_in_memory();
|
|
if (state->address)
|
|
sign_extendedh(*lsrtp);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LWL)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 3)
|
|
{
|
|
case 0:
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_word_in_memory();
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFF) | (word << 8);
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
|
|
break;
|
|
}
|
|
if(state->address)
|
|
sign_extended(*lsrtp);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LW)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_word_in_memory();
|
|
if (state->address)
|
|
sign_extended(*lsrtp);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LBU)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_byte_in_memory();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LHU)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_hword_in_memory();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LWR)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 3)
|
|
{
|
|
case 0:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | ((word >> 24) & 0xFF);
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | ((word >> 16) & 0xFFFF);
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | ((word >> 8) & 0XFFFFFF);
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
sign_extended(*lsrtp);
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LWU)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_word_in_memory();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SB)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_byte = (unsigned char)(*lsrtp & 0xFF);
|
|
write_byte_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SH)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_hword = (unsigned short)(*lsrtp & 0xFFFF);
|
|
write_hword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SWL)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int old_word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 3)
|
|
{
|
|
case 0:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->cpu_word = (unsigned int)*lsrtp;
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &old_word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_word = ((unsigned int)*lsrtp >> 8) | ((unsigned int) old_word & 0xFF000000);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &old_word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_word = ((unsigned int)*lsrtp >> 16) | ((unsigned int) old_word & 0xFFFF0000);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 3:
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_byte = (unsigned char)(*lsrtp >> 24);
|
|
write_byte_in_memory();
|
|
CHECK_MEMORY();
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SW)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_word = (unsigned int)(*lsrtp & 0xFFFFFFFF);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SDL)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int old_word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 7)
|
|
{
|
|
case 0:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->cpu_dword = *lsrtp;
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 8)|(old_word & 0xFF00000000000000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 16)|(old_word & 0xFFFF000000000000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 24)|(old_word & 0xFFFFFF0000000000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 4:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 32)|(old_word & 0xFFFFFFFF00000000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 5:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 40)|(old_word & 0xFFFFFFFFFF000000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 6:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 48)|(old_word & 0xFFFFFFFFFFFF0000LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 7:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 56)|(old_word & 0xFFFFFFFFFFFFFF00LL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SDR)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int old_word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 7)
|
|
{
|
|
case 0:
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 56) | (old_word & 0x00FFFFFFFFFFFFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 48) | (old_word & 0x0000FFFFFFFFFFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 40) | (old_word & 0x000000FFFFFFFFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 32) | (old_word & 0x00000000FFFFFFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 4:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 24) | (old_word & 0x0000000000FFFFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 5:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 16) | (old_word & 0x000000000000FFFFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 6:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->rdword = &old_word;
|
|
read_dword_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_dword = (*lsrtp << 8) | (old_word & 0x00000000000000FFLL);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 7:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
|
state->cpu_dword = *lsrtp;
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SWR)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
unsigned long long int old_word = 0;
|
|
ADD_TO_PC(1);
|
|
switch ((lsaddr) & 3)
|
|
{
|
|
case 0:
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = &old_word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_word = ((unsigned int)*lsrtp << 24) | ((unsigned int) old_word & 0x00FFFFFF);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 1:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &old_word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_word = ((unsigned int)*lsrtp << 16) | ((unsigned int) old_word & 0x0000FFFF);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 2:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->rdword = &old_word;
|
|
read_word_in_memory();
|
|
if(state->address)
|
|
{
|
|
state->cpu_word = ((unsigned int)*lsrtp << 8) | ((unsigned int) old_word & 0x000000FF);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
break;
|
|
case 3:
|
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
|
state->cpu_word = (unsigned int)*lsrtp;
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
break;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(CACHE)
|
|
{
|
|
ADD_TO_PC(1);
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LL)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_word_in_memory();
|
|
if (state->address)
|
|
{
|
|
sign_extended(*lsrtp);
|
|
state->llbit = 1;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LWC1)
|
|
{
|
|
const unsigned char lslfft = lfft;
|
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
|
unsigned long long int temp;
|
|
if (check_cop1_unusable(state)) return;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lslfaddr;
|
|
state->rdword = &temp;
|
|
read_word_in_memory();
|
|
if (state->address)
|
|
*((int*)state->reg_cop1_simple[lslfft]) = (int) *state->rdword;
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LDC1)
|
|
{
|
|
const unsigned char lslfft = lfft;
|
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
|
if (check_cop1_unusable(state)) return;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lslfaddr;
|
|
state->rdword = (unsigned long long *)state->reg_cop1_double[lslfft];
|
|
read_dword_in_memory();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(LD)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->rdword = (unsigned long long *) lsrtp;
|
|
read_dword_in_memory();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SC)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
if(state->llbit)
|
|
{
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_word = (unsigned int)(*lsrtp & 0xFFFFFFFF);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
state->llbit = 0;
|
|
*lsrtp = 1;
|
|
}
|
|
else
|
|
{
|
|
*lsrtp = 0;
|
|
}
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SWC1)
|
|
{
|
|
const unsigned char lslfft = lfft;
|
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
|
if (check_cop1_unusable(state)) return;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lslfaddr;
|
|
state->cpu_word = *((int*)state->reg_cop1_simple[lslfft]);
|
|
write_word_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SDC1)
|
|
{
|
|
const unsigned char lslfft = lfft;
|
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
|
if (check_cop1_unusable(state)) return;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lslfaddr;
|
|
state->cpu_dword = *((unsigned long long*)state->reg_cop1_double[lslfft]);
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|
|
|
|
DECLARE_INSTRUCTION(SD)
|
|
{
|
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
|
long long int *lsrtp = &irt;
|
|
ADD_TO_PC(1);
|
|
state->address = (unsigned int) lsaddr;
|
|
state->cpu_dword = *lsrtp;
|
|
write_dword_in_memory();
|
|
CHECK_MEMORY();
|
|
}
|