/**
 * TrueReality - n64/cop2.c
 * Copyright (C) 1998 Niki W. Waibel
 *
 * This program is free software; you can redistribute it and/
 * or modify it under the terms of the GNU General Public Li-
 * cence as published by the Free Software Foundation; either
 * version 2 of the Licence, or any later version.
 *
 * This program is distributed in the hope that it will be use-
 * ful, but WITHOUT ANY WARRANTY; without even the implied war-
 * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public Licence for more details.
 *
 * You should have received a copy of the GNU General Public
 * Licence along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 * USA.
 *
 * Information about me (the author):
 *   Niki W. Waibel, Reichenau 20, 6890 Lustenau, Austria - EUROPE
 *   niki.waibel@gmx.net
**/





#include <stdio.h>
#include "../config.h"
#include "../parser_extern.h"
#include "type_sizes.h"
#include "memory.h"
#include "mnemonic.h"
#include "registers.h"
#include "cpu.h"
#include "cop0.h"



#ifdef DEBUG
   #include "../debug.h"
#endif





/* cop2 rs instruction pointer */
void *cop2_rs_instruction[32];

/* cop2 rt instruction pointer */
void *cop2_rt_instruction[32];

/* cop2 function instruction pointer */
void *cop2_instruction[64];





/******************************************************************************\
*                                                                              *
*   CoProcessor2 (COP2)                                                        *
*                                                                              *
\******************************************************************************/

/* 32 cop2 rs instructions */

void rs4300i_cop2_rs_mf()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mfc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)(sWORD)reg.cpr[2][rs4300i_RD()];
   
   //cop2 unusable exception
}

void rs4300i_cop2_rs_dmf()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dmfc2   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = reg.cpr[2][rs4300i_RD()];

   //cop2 unusable exception
   //reserved instruction exception
}

void rs4300i_cop2_rs_cf()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("cfc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)reg.ccr[2][rs4300i_RD()];

   //cop2 unusable exception
}

void rs4300i_cop2_rs_mt()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mtc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.cpr[2][rs4300i_RD()] = reg.r[rs4300i_RT()];
   
   //cop2 unusable exception
}

void rs4300i_cop2_rs_dmt()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dmtc2   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.cpr[2][rs4300i_RD()] = reg.r[rs4300i_RT()];
   
   //cop2 unusable exception
   //reserved instruction exception
}

void rs4300i_cop2_rs_ct()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ctc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RT(), rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.ccr[2][rs4300i_RD()] = reg.r[rs4300i_RT()];
   
   //cop2 unusable exception
}

void rs4300i_cop2_rs_bc()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_XINST
      printf(" cop2 bc (rt) instruction\n");
#endif
   }
#endif

   ((void (*)()) cop2_rt_instruction[rs4300i_RT()])();
  
}

void rs4300i_cop2_rs_reserved()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" reserved (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}

void rs4300i_cop2_rs_co()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_XINST
      printf(" cop2 co (funct) instruction:");
#endif
   }
#endif

   ((void (*)()) cop2_instruction[rs4300i_Funct()])();
   
}



/* 32 cop2 rt instructions */

void rs4300i_cop2_rt_bcf()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" bcf (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}

void rs4300i_cop2_rt_bct()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" bct (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}

void rs4300i_cop2_rt_bcfl()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" bcfl (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}

void rs4300i_cop2_rt_bctl()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" bctl (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}

void rs4300i_cop2_rt_reserved()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" reserved (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}






/* 64 cop2 function instructions */

/*
void rs4300i_cop0_()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" (NOT IMPLEMENTED) \n");
#endif

#ifdef HALT
   reg.halt = 1;
#endif
}
*/

