/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *   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,   (PC->f.j.inst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &reg[0],  0, 0)
DECLARE_JUMP(JAL, (PC->f.j.inst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &reg[31], 0, 0)
DECLARE_JUMP(BEQ,     PCADDR + (iimmediate+1)*4, irs == irt, &reg[0], 0, 0)
DECLARE_JUMP(BNE,     PCADDR + (iimmediate+1)*4, irs != irt, &reg[0], 0, 0)
DECLARE_JUMP(BLEZ,    PCADDR + (iimmediate+1)*4, irs <= 0,   &reg[0], 0, 0)
DECLARE_JUMP(BGTZ,    PCADDR + (iimmediate+1)*4, irs > 0,    &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, &reg[0], 1, 0)
DECLARE_JUMP(BNEL,    PCADDR + (iimmediate+1)*4, irs != irt, &reg[0], 1, 0)
DECLARE_JUMP(BLEZL,   PCADDR + (iimmediate+1)*4, irs <= 0,   &reg[0], 1, 0)
DECLARE_JUMP(BGTZL,   PCADDR + (iimmediate+1)*4, irs > 0,    &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 = PC->f.i.rt;
   unsigned long long int word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 7)
     {
      case 0:
    address = (unsigned int) lsaddr;
    rdword = (unsigned long long *) lsrtp;
    read_dword_in_memory();
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFF) | (word << 8);
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
    break;
      case 4:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFF) | (word << 32);
    break;
      case 5:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFLL) | (word << 40);
    break;
      case 6:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFFLL) | (word << 48);
    break;
      case 7:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFFLL) | (word << 56);
    break;
     }
}

DECLARE_INSTRUCTION(LDR)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   unsigned long long int word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 7)
     {
      case 0:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | (word >> 56);
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | (word >> 48);
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | (word >> 40);
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFF00000000LL) | (word >> 32);
    break;
      case 4:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFF0000000000LL) | (word >> 24);
    break;
      case 5:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFF000000000000LL) | (word >> 16);
    break;
      case 6:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &word;
    read_dword_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFF00000000000000LL) | (word >> 8);
    break;
      case 7:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    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 = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_byte_in_memory();
   if (address)
     sign_extendedb(*lsrtp);
}

DECLARE_INSTRUCTION(LH)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_hword_in_memory();
   if (address)
     sign_extendedh(*lsrtp);
}

DECLARE_INSTRUCTION(LWL)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   unsigned long long int word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 3)
     {
      case 0:
    address = (unsigned int) lsaddr;
    rdword = (unsigned long long *) lsrtp;
    read_word_in_memory();
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFF) | (word << 8);
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
    break;
     }
   if(address)
     sign_extended(*lsrtp);
}

DECLARE_INSTRUCTION(LW)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_word_in_memory();
   if (address)
     sign_extended(*lsrtp);
}

DECLARE_INSTRUCTION(LBU)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_byte_in_memory();
}

DECLARE_INSTRUCTION(LHU)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_hword_in_memory();
}

DECLARE_INSTRUCTION(LWR)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   unsigned long long int word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 3)
     {
      case 0:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | ((word >> 24) & 0xFF);
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | ((word >> 16) & 0xFFFF);
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &word;
    read_word_in_memory();
    if(address)
      *lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | ((word >> 8) & 0XFFFFFF);
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = (unsigned long long *) lsrtp;
    read_word_in_memory();
    if(address)
      sign_extended(*lsrtp);
     }
}

DECLARE_INSTRUCTION(LWU)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_word_in_memory();
}

DECLARE_INSTRUCTION(SB)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   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 = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   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 = PC->f.i.rt;
   unsigned long long int old_word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 3)
     {
      case 0:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    word = (unsigned int)*lsrtp;
    write_word_in_memory();
    CHECK_MEMORY();
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &old_word;
    read_word_in_memory();
    if(address)
      {
         word = ((unsigned int)*lsrtp >> 8) | ((unsigned int) old_word & 0xFF000000);
         write_word_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &old_word;
    read_word_in_memory();
    if(address)
      {
         word = ((unsigned int)*lsrtp >> 16) | ((unsigned int) old_word & 0xFFFF0000);
         write_word_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 3:
    address = (unsigned int) lsaddr;
    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 = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   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 = PC->f.i.rt;
   unsigned long long int old_word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 7)
     {
      case 0:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    dword = *lsrtp;
    write_dword_in_memory();
    CHECK_MEMORY();
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 8)|(old_word & 0xFF00000000000000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 16)|(old_word & 0xFFFF000000000000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 24)|(old_word & 0xFFFFFF0000000000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 4:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 32)|(old_word & 0xFFFFFFFF00000000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 5:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 40)|(old_word & 0xFFFFFFFFFF000000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 6:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = ((unsigned long long)*lsrtp >> 48)|(old_word & 0xFFFFFFFFFFFF0000LL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 7:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         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 = PC->f.i.rt;
   unsigned long long int old_word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 7)
     {
      case 0:
    address = (unsigned int) lsaddr;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 56) | (old_word & 0x00FFFFFFFFFFFFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 48) | (old_word & 0x0000FFFFFFFFFFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 40) | (old_word & 0x000000FFFFFFFFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 32) | (old_word & 0x00000000FFFFFFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 4:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 24) | (old_word & 0x0000000000FFFFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 5:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 16) | (old_word & 0x000000000000FFFFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 6:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    rdword = &old_word;
    read_dword_in_memory();
    if(address)
      {
         dword = (*lsrtp << 8) | (old_word & 0x00000000000000FFLL);
         write_dword_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 7:
    address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
    dword = *lsrtp;
    write_dword_in_memory();
    CHECK_MEMORY();
    break;
     }
}

DECLARE_INSTRUCTION(SWR)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   unsigned long long int old_word = 0;
   ADD_TO_PC(1);
   switch ((lsaddr) & 3)
     {
      case 0:
    address = (unsigned int) lsaddr;
    rdword = &old_word;
    read_word_in_memory();
    if(address)
      {
         word = ((unsigned int)*lsrtp << 24) | ((unsigned int) old_word & 0x00FFFFFF);
         write_word_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 1:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &old_word;
    read_word_in_memory();
    if(address)
      {
         word = ((unsigned int)*lsrtp << 16) | ((unsigned int) old_word & 0x0000FFFF);
         write_word_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 2:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    rdword = &old_word;
    read_word_in_memory();
    if(address)
      {
         word = ((unsigned int)*lsrtp << 8) | ((unsigned int) old_word & 0x000000FF);
         write_word_in_memory();
         CHECK_MEMORY();
      }
    break;
      case 3:
    address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
    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 = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_word_in_memory();
   if (address)
     {
    sign_extended(*lsrtp);
    llbit = 1;
     }
}

DECLARE_INSTRUCTION(LWC1)
{
   const unsigned char lslfft = lfft;
   const unsigned int lslfaddr = (unsigned int)(lfoffset + reg[lfbase]);
   unsigned long long int temp;
   if (check_cop1_unusable()) return;
   ADD_TO_PC(1);
   address = (unsigned int) lslfaddr;
   rdword = &temp;
   read_word_in_memory();
   if (address)
     *((int*)reg_cop1_simple[lslfft]) = (int) *rdword;
}

DECLARE_INSTRUCTION(LDC1)
{
   const unsigned char lslfft = lfft;
   const unsigned int lslfaddr = (unsigned int)(lfoffset + reg[lfbase]);
   if (check_cop1_unusable()) return;
   ADD_TO_PC(1);
   address = (unsigned int) lslfaddr;
   rdword = (unsigned long long *)reg_cop1_double[lslfft];
   read_dword_in_memory();
}

DECLARE_INSTRUCTION(LD)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   rdword = (unsigned long long *) lsrtp;
   read_dword_in_memory();
}

DECLARE_INSTRUCTION(SC)
{
   const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
   long long int *lsrtp = PC->f.i.rt;
   ADD_TO_PC(1);
   if(llbit)
   {
      address = (unsigned int) lsaddr;
      word = (unsigned int)(*lsrtp & 0xFFFFFFFF);
      write_word_in_memory();
      CHECK_MEMORY();
      llbit = 0;
      *lsrtp = 1;
   }
   else
   {
      *lsrtp = 0;
   }
}

DECLARE_INSTRUCTION(SWC1)
{
   const unsigned char lslfft = lfft;
   const unsigned int lslfaddr = (unsigned int)(lfoffset + reg[lfbase]);
   if (check_cop1_unusable()) return;
   ADD_TO_PC(1);
   address = (unsigned int) lslfaddr;
   word = *((int*)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 + reg[lfbase]);
   if (check_cop1_unusable()) return;
   ADD_TO_PC(1);
   address = (unsigned int) lslfaddr;
   dword = *((unsigned long long*)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 = PC->f.i.rt;
   ADD_TO_PC(1);
   address = (unsigned int) lsaddr;
   dword = *lsrtp;
   write_dword_in_memory();
   CHECK_MEMORY();
}
