/**
 * TrueReality - n64/cpu.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 <stdlib.h>
#include "../config.h"
#include "type_sizes.h"
#include "memory_extern.h"
#include "memory.h"
#include "mnemonic.h"
#include "registers.h"
#include "exceptions.h"
#include "interrupts.h"
#include "../dispatch.h"
#include "../parser_extern.h"
#include "cop2.h"
#include "cop1.h"
#include "cop0.h"
#include "cpu.h"



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







struct rs4300i_reg reg;




                      





/* cpu instruction pointer */

void *instruction[64];



/* cpu special instruction pointer */

void *special_instruction[64];



/* regimm instruction pointer */

void *regimm_instruction[32];



/* 64 cpu instructions */

static void rs4300i_special();
static void rs4300i_regimm();
static void rs4300i_j();
static void rs4300i_jal();
static void rs4300i_beq();
static void rs4300i_bne();
static void rs4300i_blez();
static void rs4300i_bgtz();
static void rs4300i_addi();
static void rs4300i_addiu();
static void rs4300i_slti();
static void rs4300i_sltiu();
static void rs4300i_andi();
static void rs4300i_ori();
static void rs4300i_xori();
static void rs4300i_lui();
static void rs4300i_cop0();
static void rs4300i_cop1();
static void rs4300i_cop2();
static void rs4300i_beql();
static void rs4300i_bnel();
static void rs4300i_blezl();
static void rs4300i_bgtzl();
static void rs4300i_daddi();
static void rs4300i_daddiu();
static void rs4300i_ldl();
static void rs4300i_ldr();
static void rs4300i_lb();
static void rs4300i_lh();
static void rs4300i_lwl();
static void rs4300i_lw();
static void rs4300i_lbu();
static void rs4300i_lhu();
static void rs4300i_lwr();
static void rs4300i_lwu();
static void rs4300i_sb();
static void rs4300i_sh();
static void rs4300i_swl();
static void rs4300i_sw();
static void rs4300i_sdl();
static void rs4300i_sdr();
static void rs4300i_swr();
static void rs4300i_cache();
static void rs4300i_ll();
static void rs4300i_lwc1();
static void rs4300i_lwc2();
static void rs4300i_lld();
static void rs4300i_ldc1();
static void rs4300i_ldc2();
static void rs4300i_ld();
static void rs4300i_sc();
static void rs4300i_swc1();
static void rs4300i_swc2();
static void rs4300i_scd();
static void rs4300i_sdc1();
static void rs4300i_sdc2();
static void rs4300i_sd();
static void rs4300i_reserved();




/* 64 cpu special instructions */

static void rs4300i_special_sll();
static void rs4300i_special_srl();
static void rs4300i_special_sra();
static void rs4300i_special_sllv();
static void rs4300i_special_srlv();
static void rs4300i_special_srav();
static void rs4300i_special_jr();
static void rs4300i_special_jalr();
static void rs4300i_special_syscall();
static void rs4300i_special_break();
static void rs4300i_special_sync();
static void rs4300i_special_mfhi();
static void rs4300i_special_mthi();
static void rs4300i_special_mflo();
static void rs4300i_special_mtlo();
static void rs4300i_special_dsllv();
static void rs4300i_special_dsrlv();
static void rs4300i_special_dsrav();
static void rs4300i_special_mult();
static void rs4300i_special_multu();
static void rs4300i_special_div();
static void rs4300i_special_divu();
static void rs4300i_special_dmult();
static void rs4300i_special_dmultu();
static void rs4300i_special_ddiv();
static void rs4300i_special_ddivu();
static void rs4300i_special_add();
static void rs4300i_special_addu();
static void rs4300i_special_sub();
static void rs4300i_special_subu();
static void rs4300i_special_and();
static void rs4300i_special_or();
static void rs4300i_special_xor();
static void rs4300i_special_nor();
static void rs4300i_special_slt();
static void rs4300i_special_sltu();
static void rs4300i_special_dadd();
static void rs4300i_special_daddu();
static void rs4300i_special_dsub();
static void rs4300i_special_dsubu();
static void rs4300i_special_tge();
static void rs4300i_special_tgeu();
static void rs4300i_special_tlt();
static void rs4300i_special_tltu();
static void rs4300i_special_teq();
static void rs4300i_special_tne();
static void rs4300i_special_dsll();
static void rs4300i_special_dsrl();
static void rs4300i_special_dsra();
static void rs4300i_special_dsll32();
static void rs4300i_special_reserved();
static void rs4300i_special_dsrl32();
static void rs4300i_special_dsra32();




/* 32 cpu regimm instructions */

static void rs4300i_regimm_bltz();
static void rs4300i_regimm_bgez();
static void rs4300i_regimm_bltzl();
static void rs4300i_regimm_bgezl();
static void rs4300i_regimm_tgei();
static void rs4300i_regimm_tgeiu();
static void rs4300i_regimm_tlti();
static void rs4300i_regimm_tltiu();
static void rs4300i_regimm_teqi();
static void rs4300i_regimm_tnei();
static void rs4300i_regimm_bltzal();
static void rs4300i_regimm_bgezal();
static void rs4300i_regimm_bltzall();
static void rs4300i_regimm_bgezall();
static void rs4300i_regimm_reserved();








void rs4300i_doCode()
{
#ifdef HALT
        if(reg.halt)
                return;
#endif



        if(reg.do_or_check_sthg)
        {
                if(reg.do_or_check_sthg & RS4300I_DO_SI_INTERRUPT)
                        rs4300i_MI_Intr_SI();

                if(reg.do_or_check_sthg & RS4300I_DO_SP_INTERRUPT)
                        rs4300i_MI_Intr_SP();

                if(reg.do_or_check_sthg & RS4300I_DO_PI_INTERRUPT)
                        rs4300i_MI_Intr_PI();

                if(reg.do_or_check_sthg & RS4300I_CHECK_MI_INTERRUPTS)
                        rs4300i_Check_MI_Interrupts();

                if(reg.do_or_check_sthg & RS4300I_CHECK_CPU_INTERRUPTS)
                        rs4300i_Check_CPU_Interrupts();

                if(reg.do_or_check_sthg & RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION)
                        rs4300i_integer_overflow_exception();

                if(reg.do_or_check_sthg & RS4300I_DO_FLOATING_POINT_EXCEPTION)
                        rs4300i_floating_point_exception();

                if(reg.do_or_check_sthg & RS4300I_DO_TRAP_EXCEPTION)
                        rs4300i_trap_exception();

                if(reg.do_or_check_sthg & RS4300I_DO_SYSCALL_EXCEPTION)
                        rs4300i_syscall_exception();

                reg.do_or_check_sthg = RS4300I_DO_OR_CHECK_NOTHING;
        }



        /* if (COUNT reg == COMPARE reg) then { generate a comp intr } */
        if((reg.cpr[0][COUNT] & 0xffffffff) == reg.cpr[0][COMPARE])
        {
#ifdef DEBUG_INTERRUPT_COMPARE
                if(prefs.debug & DBG_INTR_COMP)
                        printf("call compare interrupt handler (COUNT=%016llx, PC=%08lx)\n", reg.cpr[0][9], reg.pc);
#endif
                rs4300i_CompareInterrupt();
        }



        if(reg.cpr[0][COUNT] == rs4300i_interrupts[2].time)
        {
#ifdef DEBUG_INTERRUPT_VI
                if(prefs.debug & DBG_INTR_VI)
                        printf("call vi interrupt handler (COUNT=%016llx, PC=%08lx)\n", reg.cpr[0][9], reg.pc);
#endif
                ((void (*)())rs4300i_interrupts[2].handler)();
        }



        /* execute instruction */

#ifdef DEBUG_PC
        if(prefs.debug & DBG_CPU_COUNT)
                printf("%016llx: ", reg.cpr[0][COUNT]);
        if(prefs.debug & DBG_CPU_PC)
                printf("%08lx: ", reg.pc);
#endif


        //puts("--- DEBUG --- DEBUG --- DEBUG ---"); fflush(stdout);

        //printf("%d\n", rs4300i_Opcode()); fflush(stdout);

        ((void (*)()) instruction[rs4300i_Opcode()])();

                
        //puts("--- DEBUG --- DEBUG --- DEBUG ---"); fflush(stdout);
                
        switch(reg.delay)
        {
            case -1:   /* next instruction is at pc_delay */
                reg.delay = 0;
                reg.pc = reg.pc_delay;
                break;
 
            case  1:   /* a delayed pc was stored into pc_delay      */
                       /* next instr is at pc+4 (case 0 is executed) */
                       /* next instr is at pc_delay                  */
                reg.delay = -1;
    
            case 0:    /* normal execution */
                reg.pc += 4;
    
        } /* switch(reg.delay) */



        /* do common things */
        
        reg.r[0] = 0;
        reg.cpr[0][COUNT]++;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_REG)
        {
                rs4300i_printCPURegister();
                rs4300i_printCP0Register();
        }
#endif


   
} /* void rs4300i_doCode() */




  
void rs4300i_Reset()
{
        int i, j;





        /* debugging */
#ifdef HALT
        reg.halt = 0;
#endif
        reg.do_or_check_sthg = RS4300I_DO_OR_CHECK_NOTHING;

   
   
        /* cpu registers */
   
        /* reg.pc = 0xbfc00000; */
        reg.pc = 0xa4000040;

        for(i=0; i<32; i++)
                reg.r[i] = 0;
      
        reg.r[20] = 0x0000000000000001ULL;
        reg.r[22] = 0x000000000000003fULL;
        reg.r[29] = 0x0000000000400000ULL;

        reg.hi = 0;
        reg.lo = 0;

        reg.llbit = 0;

        reg.delay = 0;



        /* cop0/1/2 registers */
   
        for(j=0; j<=2; j++)
                for(i=0; i<32; i++)
                {
                        reg.cpr[j][i] = 0;
                        reg.ccr[j][i] = 0;
                }
      
        reg.cpr[0][STATUS] = 0x70400004;
        reg.cpr[0][RANDOM] = 0x0000002f;
        reg.cpr[0][CONFIG] = 0x00066463;
        reg.cpr[0][PRID]   = 0x00000b00;
        
        reg.ccr[1][0]      = 0x00000511;


   
        /* interrupts */
   
        rs4300i_InitInterrupts();



        /* memory */
        



   
/******************************************************************************\
*                                                                              *
*   Central Processing Unit (CPU)                                              *
*                                                                              *
\******************************************************************************/
   
        /* 64 cpu instructions */

        instruction[ 0] = (void *) rs4300i_special;
        instruction[ 1] = (void *) rs4300i_regimm;
        instruction[ 2] = (void *) rs4300i_j;
        instruction[ 3] = (void *) rs4300i_jal;
        instruction[ 4] = (void *) rs4300i_beq;
        instruction[ 5] = (void *) rs4300i_bne;
        instruction[ 6] = (void *) rs4300i_blez;
        instruction[ 7] = (void *) rs4300i_bgtz;
        instruction[ 8] = (void *) rs4300i_addi;
        instruction[ 9] = (void *) rs4300i_addiu;
        instruction[10] = (void *) rs4300i_slti;
        instruction[11] = (void *) rs4300i_sltiu;
        instruction[12] = (void *) rs4300i_andi;
        instruction[13] = (void *) rs4300i_ori;
        instruction[14] = (void *) rs4300i_xori;
        instruction[15] = (void *) rs4300i_lui;
        instruction[16] = (void *) rs4300i_cop0;
        instruction[17] = (void *) rs4300i_cop1;
        instruction[18] = (void *) rs4300i_cop2;
        instruction[19] = (void *) rs4300i_reserved;
        instruction[20] = (void *) rs4300i_beql;
        instruction[21] = (void *) rs4300i_bnel;
        instruction[22] = (void *) rs4300i_blezl;
        instruction[23] = (void *) rs4300i_bgtzl;
        instruction[24] = (void *) rs4300i_daddi;
        instruction[25] = (void *) rs4300i_daddiu;
        instruction[26] = (void *) rs4300i_ldl;
        instruction[27] = (void *) rs4300i_ldr;
        instruction[28] = (void *) rs4300i_reserved;
        instruction[29] = (void *) rs4300i_reserved;
        instruction[30] = (void *) rs4300i_reserved;
        instruction[31] = (void *) rs4300i_reserved;
        instruction[32] = (void *) rs4300i_lb;
        instruction[33] = (void *) rs4300i_lh;
        instruction[34] = (void *) rs4300i_lwl;
        instruction[35] = (void *) rs4300i_lw;
        instruction[36] = (void *) rs4300i_lbu;
        instruction[37] = (void *) rs4300i_lhu;
        instruction[38] = (void *) rs4300i_lwr;
        instruction[39] = (void *) rs4300i_lwu;
        instruction[40] = (void *) rs4300i_sb;
        instruction[41] = (void *) rs4300i_sh;
        instruction[42] = (void *) rs4300i_swl;
        instruction[43] = (void *) rs4300i_sw;
        instruction[44] = (void *) rs4300i_sdl;
        instruction[45] = (void *) rs4300i_sdr;
        instruction[46] = (void *) rs4300i_swr;
        instruction[47] = (void *) rs4300i_cache;
        instruction[48] = (void *) rs4300i_ll;
        instruction[49] = (void *) rs4300i_lwc1;
        instruction[50] = (void *) rs4300i_lwc2;
        instruction[51] = (void *) rs4300i_reserved;
        instruction[52] = (void *) rs4300i_lld;
        instruction[53] = (void *) rs4300i_ldc1;
        instruction[54] = (void *) rs4300i_ldc2;
        instruction[55] = (void *) rs4300i_ld;
        instruction[56] = (void *) rs4300i_sc;
        instruction[57] = (void *) rs4300i_swc1;
        instruction[58] = (void *) rs4300i_swc2;
        instruction[59] = (void *) rs4300i_reserved;
        instruction[60] = (void *) rs4300i_scd;
        instruction[61] = (void *) rs4300i_sdc1;
        instruction[62] = (void *) rs4300i_sdc2;
        instruction[63] = (void *) rs4300i_sd;
        
        /* 64 cpu special instructions */
     
        special_instruction[ 0] = (void *) rs4300i_special_sll;    
        special_instruction[ 1] = (void *) rs4300i_special_reserved;
        special_instruction[ 2] = (void *) rs4300i_special_srl;    
        special_instruction[ 3] = (void *) rs4300i_special_sra;    
        special_instruction[ 4] = (void *) rs4300i_special_sllv;   
        special_instruction[ 5] = (void *) rs4300i_special_reserved;
        special_instruction[ 6] = (void *) rs4300i_special_srlv;   
        special_instruction[ 7] = (void *) rs4300i_special_srav;   
        special_instruction[ 8] = (void *) rs4300i_special_jr;     
        special_instruction[ 9] = (void *) rs4300i_special_jalr;   
        special_instruction[10] = (void *) rs4300i_special_reserved;
        special_instruction[11] = (void *) rs4300i_special_reserved;
        special_instruction[12] = (void *) rs4300i_special_syscall;
        special_instruction[13] = (void *) rs4300i_special_break;  
        special_instruction[14] = (void *) rs4300i_special_reserved;
        special_instruction[15] = (void *) rs4300i_special_sync;   
        special_instruction[16] = (void *) rs4300i_special_mfhi;   
        special_instruction[17] = (void *) rs4300i_special_mthi;   
        special_instruction[18] = (void *) rs4300i_special_mflo;   
        special_instruction[19] = (void *) rs4300i_special_mtlo;   
        special_instruction[20] = (void *) rs4300i_special_dsllv;  
        special_instruction[21] = (void *) rs4300i_special_reserved;
        special_instruction[22] = (void *) rs4300i_special_dsrlv;  
        special_instruction[23] = (void *) rs4300i_special_dsrav;  
        special_instruction[24] = (void *) rs4300i_special_mult;   
        special_instruction[25] = (void *) rs4300i_special_multu;  
        special_instruction[26] = (void *) rs4300i_special_div;    
        special_instruction[27] = (void *) rs4300i_special_divu;   
        special_instruction[28] = (void *) rs4300i_special_dmult;  
        special_instruction[29] = (void *) rs4300i_special_dmultu; 
        special_instruction[30] = (void *) rs4300i_special_ddiv;   
        special_instruction[31] = (void *) rs4300i_special_ddivu;  
        special_instruction[32] = (void *) rs4300i_special_add;    
        special_instruction[33] = (void *) rs4300i_special_addu;   
        special_instruction[34] = (void *) rs4300i_special_sub;    
        special_instruction[35] = (void *) rs4300i_special_subu;   
        special_instruction[36] = (void *) rs4300i_special_and;    
        special_instruction[37] = (void *) rs4300i_special_or;     
        special_instruction[38] = (void *) rs4300i_special_xor;    
        special_instruction[39] = (void *) rs4300i_special_nor;    
        special_instruction[40] = (void *) rs4300i_special_reserved;
        special_instruction[41] = (void *) rs4300i_special_reserved;
        special_instruction[42] = (void *) rs4300i_special_slt;    
        special_instruction[43] = (void *) rs4300i_special_sltu;   
        special_instruction[44] = (void *) rs4300i_special_dadd;   
        special_instruction[45] = (void *) rs4300i_special_daddu;  
        special_instruction[46] = (void *) rs4300i_special_dsub;   
        special_instruction[47] = (void *) rs4300i_special_dsubu;  
        special_instruction[48] = (void *) rs4300i_special_tge;    
        special_instruction[49] = (void *) rs4300i_special_tgeu;   
        special_instruction[50] = (void *) rs4300i_special_tlt;    
        special_instruction[51] = (void *) rs4300i_special_tltu;   
        special_instruction[52] = (void *) rs4300i_special_teq;    
        special_instruction[53] = (void *) rs4300i_special_reserved;
        special_instruction[54] = (void *) rs4300i_special_tne;    
        special_instruction[55] = (void *) rs4300i_special_reserved;
        special_instruction[56] = (void *) rs4300i_special_dsll;   
        special_instruction[57] = (void *) rs4300i_special_reserved;
        special_instruction[58] = (void *) rs4300i_special_dsrl;   
        special_instruction[59] = (void *) rs4300i_special_dsra;   
        special_instruction[60] = (void *) rs4300i_special_dsll32; 
        special_instruction[61] = (void *) rs4300i_special_reserved;
        special_instruction[62] = (void *) rs4300i_special_dsrl32;
        special_instruction[63] = (void *) rs4300i_special_dsra32;
        
        /* cpu regimm (rt) instructions */
        
        regimm_instruction[ 0] = (void *) rs4300i_regimm_bltz;   
        regimm_instruction[ 1] = (void *) rs4300i_regimm_bgez;   
        regimm_instruction[ 2] = (void *) rs4300i_regimm_bltzl;  
        regimm_instruction[ 3] = (void *) rs4300i_regimm_bgezl;  
        regimm_instruction[ 4] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[ 5] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[ 6] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[ 7] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[ 8] = (void *) rs4300i_regimm_tgei;   
        regimm_instruction[ 9] = (void *) rs4300i_regimm_tgeiu;  
        regimm_instruction[10] = (void *) rs4300i_regimm_tlti;   
        regimm_instruction[11] = (void *) rs4300i_regimm_tltiu;  
        regimm_instruction[12] = (void *) rs4300i_regimm_teqi;   
        regimm_instruction[13] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[14] = (void *) rs4300i_regimm_tnei;   
        regimm_instruction[15] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[16] = (void *) rs4300i_regimm_bltzal; 
        regimm_instruction[17] = (void *) rs4300i_regimm_bgezal; 
        regimm_instruction[18] = (void *) rs4300i_regimm_bltzall;
        regimm_instruction[19] = (void *) rs4300i_regimm_bgezall;
        regimm_instruction[20] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[21] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[22] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[23] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[24] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[25] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[26] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[27] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[28] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[29] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[30] = (void *) rs4300i_regimm_reserved;
        regimm_instruction[31] = (void *) rs4300i_regimm_reserved;
     
     
     
/******************************************************************************\
*                                                                              *
*   CoProcessor0 (COP0)                                                        *
*                                                                              *
\******************************************************************************/

        /* cop0 (rs) instructions */
     
        cop0_rs_instruction[ 0] = (void *) rs4300i_cop0_rs_mf;           
        cop0_rs_instruction[ 1] = (void *) rs4300i_cop0_rs_dmf;          
        cop0_rs_instruction[ 2] = (void *) rs4300i_cop0_rs_cf;           
        cop0_rs_instruction[ 3] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[ 4] = (void *) rs4300i_cop0_rs_mt;           
        cop0_rs_instruction[ 5] = (void *) rs4300i_cop0_rs_dmt;          
        cop0_rs_instruction[ 6] = (void *) rs4300i_cop0_rs_ct;           
        cop0_rs_instruction[ 7] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[ 8] = (void *) rs4300i_cop0_rs_bc;           
        cop0_rs_instruction[ 9] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[10] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[11] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[12] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[13] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[14] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[15] = (void *) rs4300i_cop0_rs_reserved;     
        cop0_rs_instruction[16] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[17] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[18] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[19] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[20] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[21] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[22] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[23] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[24] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[25] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[26] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[27] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[28] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[29] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[30] = (void *) rs4300i_cop0_rs_co;           
        cop0_rs_instruction[31] = (void *) rs4300i_cop0_rs_co;
     
        /* cop0 (rt) instructions */
        
        cop0_rt_instruction[ 0] = (void *) rs4300i_cop0_rt_bcf;    
        cop0_rt_instruction[ 1] = (void *) rs4300i_cop0_rt_bct;    
        cop0_rt_instruction[ 2] = (void *) rs4300i_cop0_rt_bcfl;   
        cop0_rt_instruction[ 3] = (void *) rs4300i_cop0_rt_bctl;   
        cop0_rt_instruction[ 4] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[ 5] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[ 6] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[ 7] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[ 8] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[ 9] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[10] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[11] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[12] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[13] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[14] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[15] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[16] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[17] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[18] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[19] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[20] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[21] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[22] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[23] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[24] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[25] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[26] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[27] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[28] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[29] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[30] = (void *) rs4300i_cop0_rt_reserved;
        cop0_rt_instruction[31] = (void *) rs4300i_cop0_rt_reserved;
        
        /* cop0 instructions */
        
        cop0_instruction[ 0] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[ 1] = (void *) rs4300i_cop0_tlbr;               
        cop0_instruction[ 2] = (void *) rs4300i_cop0_tlbwi;              
        cop0_instruction[ 3] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[ 4] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[ 5] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[ 6] = (void *) rs4300i_cop0_tlbwr;              
        cop0_instruction[ 7] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[ 8] = (void *) rs4300i_cop0_tlbp;               
        cop0_instruction[ 9] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[10] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[11] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[12] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[13] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[14] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[15] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[16] = (void *) rs4300i_cop0_reserved;           
        cop0_instruction[17] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[18] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[19] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[20] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[21] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[22] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[23] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[24] = (void *) rs4300i_cop0_eret;               
        cop0_instruction[25] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[26] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[27] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[28] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[29] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[30] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[31] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[32] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[33] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[34] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[35] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[36] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[37] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[38] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[39] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[40] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[41] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[42] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[43] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[44] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[45] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[46] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[47] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[48] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[49] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[50] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[51] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[52] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[53] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[54] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[55] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[56] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[57] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[58] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[59] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[60] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[61] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[62] = (void *) rs4300i_cop0_invalid;            
        cop0_instruction[63] = (void *) rs4300i_cop0_invalid;
     
     
     
/******************************************************************************\
*                                                                              *
*   CoProcessor1 - Floating Point Unit (COP1 - FPU)                            *
*                                                                              *
\******************************************************************************/

        /* cop1 (rs) instructions */
     
        cop1_rs_instruction[ 0] = (void *) rs4300i_cop1_rs_mf;           
        cop1_rs_instruction[ 1] = (void *) rs4300i_cop1_rs_dmf;          
        cop1_rs_instruction[ 2] = (void *) rs4300i_cop1_rs_cf;           
        cop1_rs_instruction[ 3] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[ 4] = (void *) rs4300i_cop1_rs_mt;           
        cop1_rs_instruction[ 5] = (void *) rs4300i_cop1_rs_dmt;          
        cop1_rs_instruction[ 6] = (void *) rs4300i_cop1_rs_ct;           
        cop1_rs_instruction[ 7] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[ 8] = (void *) rs4300i_cop1_rs_bc;           
        cop1_rs_instruction[ 9] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[10] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[11] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[12] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[13] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[14] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[15] = (void *) rs4300i_cop1_rs_reserved;     
        cop1_rs_instruction[16] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[17] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[18] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[19] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[20] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[21] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[22] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[23] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[24] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[25] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[26] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[27] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[28] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[29] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[30] = (void *) rs4300i_cop1_rs_co;           
        cop1_rs_instruction[31] = (void *) rs4300i_cop1_rs_co;
     
        /* cop1 (rt) instructions */
        
        cop1_rt_instruction[ 0] = (void *) rs4300i_cop1_rt_bcf;    
        cop1_rt_instruction[ 1] = (void *) rs4300i_cop1_rt_bct;    
        cop1_rt_instruction[ 2] = (void *) rs4300i_cop1_rt_bcfl;   
        cop1_rt_instruction[ 3] = (void *) rs4300i_cop1_rt_bctl;   
        cop1_rt_instruction[ 4] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[ 5] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[ 6] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[ 7] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[ 8] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[ 9] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[10] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[11] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[12] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[13] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[14] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[15] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[16] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[17] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[18] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[19] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[20] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[21] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[22] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[23] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[24] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[25] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[26] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[27] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[28] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[29] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[30] = (void *) rs4300i_cop1_rt_reserved;
        cop1_rt_instruction[31] = (void *) rs4300i_cop1_rt_reserved;
        
        /* cop1 (fpu) instructions */
        
        cop1_instruction[ 0] = (void *) rs4300i_cop1_add;   
        cop1_instruction[ 1] = (void *) rs4300i_cop1_sub;
        cop1_instruction[ 2] = (void *) rs4300i_cop1_mul;
        cop1_instruction[ 3] = (void *) rs4300i_cop1_div;
        cop1_instruction[ 4] = (void *) rs4300i_cop1_sqrt;
        cop1_instruction[ 5] = (void *) rs4300i_cop1_abs;
        cop1_instruction[ 6] = (void *) rs4300i_cop1_mov;
        cop1_instruction[ 7] = (void *) rs4300i_cop1_neg;
        cop1_instruction[ 8] = (void *) rs4300i_cop1_roundl;
        cop1_instruction[ 9] = (void *) rs4300i_cop1_truncl;
        cop1_instruction[10] = (void *) rs4300i_cop1_ceill;
        cop1_instruction[11] = (void *) rs4300i_cop1_floorl;
        cop1_instruction[12] = (void *) rs4300i_cop1_roundw;
        cop1_instruction[13] = (void *) rs4300i_cop1_truncw;
        cop1_instruction[14] = (void *) rs4300i_cop1_ceilw;
        cop1_instruction[15] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[16] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[17] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[18] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[19] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[20] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[21] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[22] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[23] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[24] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[25] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[26] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[27] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[28] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[29] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[30] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[31] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[32] = (void *) rs4300i_cop1_cvts;   
        cop1_instruction[33] = (void *) rs4300i_cop1_cvtd;   
        cop1_instruction[34] = (void *) rs4300i_cop1_reserved;   
        cop1_instruction[35] = (void *) rs4300i_cop1_reserved;   
        cop1_instruction[36] = (void *) rs4300i_cop1_cvtw;   
        cop1_instruction[37] = (void *) rs4300i_cop1_cvtl;   
        cop1_instruction[38] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[39] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[40] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[41] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[42] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[43] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[44] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[45] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[46] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[47] = (void *) rs4300i_cop1_reserved;
        cop1_instruction[48] = (void *) rs4300i_cop1_c;   
        cop1_instruction[49] = (void *) rs4300i_cop1_c;   
        cop1_instruction[50] = (void *) rs4300i_cop1_c;   
        cop1_instruction[51] = (void *) rs4300i_cop1_c;   
        cop1_instruction[52] = (void *) rs4300i_cop1_c;   
        cop1_instruction[53] = (void *) rs4300i_cop1_c;   
        cop1_instruction[54] = (void *) rs4300i_cop1_c;   
        cop1_instruction[55] = (void *) rs4300i_cop1_c;   
        cop1_instruction[56] = (void *) rs4300i_cop1_c;   
        cop1_instruction[57] = (void *) rs4300i_cop1_c;   
        cop1_instruction[58] = (void *) rs4300i_cop1_c;   
        cop1_instruction[59] = (void *) rs4300i_cop1_c;   
        cop1_instruction[60] = (void *) rs4300i_cop1_c;   
        cop1_instruction[61] = (void *) rs4300i_cop1_c;   
        cop1_instruction[62] = (void *) rs4300i_cop1_c;   
        cop1_instruction[63] = (void *) rs4300i_cop1_c;
     
} /* void rs4300i_hardReset() */





/******************************************************************************\
*                                                                              *
*   Central Processing Unit (CPU)                                              *
*                                                                              *
\******************************************************************************/



static void rs4300i_special()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_XINST
      printf("special instruction:\n");
#endif
   }
#endif
   
   ((void (*)()) special_instruction[rs4300i_Funct()])();

}



static void rs4300i_regimm()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_XINST
      printf("regimm instruction:\n");
#endif
   }
#endif

   ((void (*)()) regimm_instruction[rs4300i_RT()])();

}



static void rs4300i_j()
{
        DWORD count;

#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("j       :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" 0x%08lx", (reg.pc & 0xf0000000) + (rs4300i_Target() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   if((rs4300i_Target() << 2) == (reg.pc & 0x0ffffffc))   /* if jump to same myself  */
      if(rs4300i_NCode(4) == 0x00000000)                  /*    if next instr == nop */
      {
//         printf("count: %llx\n", reg.cpr[0][COUNT]);

         count = rs4300i_interrupts[2].time;

//         if(reg.cpr[0][STATUS] & 0x00008000)   /* timer interrupt set */
            if(reg.cpr[0][COMPARE] < (count & 0xffffffff))
               if(reg.cpr[0][COMPARE] > (reg.cpr[0][COUNT] & 0xffffffff))
                  count = reg.cpr[0][COMPARE] | (reg.cpr[0][COUNT] & 0xffffffff00000000ULL);

         reg.cpr[0][COUNT] = count - 1;

//         printf("count: %llx\n\n", reg.cpr[0][COUNT]);
      }
   
   reg.delay = 1;
   reg.pc_delay = (reg.pc & 0xf0000000) + (rs4300i_Target() << 2);
   
}



static void rs4300i_jal()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("jal     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" 0x%08lx", (reg.pc & 0xf0000000) + (rs4300i_Target() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.delay = 1;
   reg.pc_delay = (reg.pc & 0xf0000000)+ (rs4300i_Target() << 2);
   reg.r[31] = reg.pc + 8;

}



static void rs4300i_beq()
{
        DWORD count;
        
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("beq     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%lu)", rs4300i_RS(), rs4300i_RT(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(reg.r[rs4300i_RS()] == reg.r[rs4300i_RT()])
   {
      if(rs4300i_I() == -1)                                  /* if jump to same myself  */
         if(rs4300i_NCode(4) == 0x00000000)                  /*    if next instr == nop */
         {
//            printf("count: %llx\n", reg.cpr[0][COUNT]);

            count = rs4300i_interrupts[2].time;

//            if(reg.cpr[0][STATUS] & 0x00008000)   /* timer interrupt set */
               if(reg.cpr[0][COMPARE] < (count & 0xffffffff))
                  if(reg.cpr[0][COMPARE] > (reg.cpr[0][COUNT] & 0xffffffff))
                     count = reg.cpr[0][COMPARE] | (reg.cpr[0][COUNT] & 0xffffffff00000000ULL);

            reg.cpr[0][COUNT] = count - 1;

//            printf("count: %llx\n\n", reg.cpr[0][COUNT]);
         }
      
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }

}



static void rs4300i_bne()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bne     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%lu)", rs4300i_RS(), rs4300i_RT(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(reg.r[rs4300i_RS()] != reg.r[rs4300i_RT()])
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
      
}



static void rs4300i_blez()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("blez    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((signed)reg.r[rs4300i_RS()]) <= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
      
}



static void rs4300i_bgtz()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgtz    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((signed)reg.r[rs4300i_RS()]) > 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
      
}





static void rs4300i_addi()
{
        sDWORD x, y, z;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("addi    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u, 0x%04hx (%hd)", rs4300i_RT(), rs4300i_RS(), (sHWORD)rs4300i_I(), (sHWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        x = (sWORD)reg.r[rs4300i_RS()];
        y = (sWORD)rs4300i_I();
        
        z = x + y;

        
        
        if((z > 0x7fffffffLL) || (z < -0x80000000LL))
                reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
        else
                reg.r[rs4300i_RT()] = (sDWORD)(sWORD)z;

}





static void rs4300i_addiu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("addiu   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%04hx (%hd)", rs4300i_RT(), rs4300i_RS(), (sHWORD)rs4300i_I(), (sHWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


    reg.r[rs4300i_RT()] = (sDWORD)(sWORD)(reg.r[rs4300i_RS()] + rs4300i_I());

}



static void rs4300i_slti()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("slti    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%ld)", rs4300i_RT(), rs4300i_RS(), rs4300i_I(), rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   if(reg.r[rs4300i_RS()] < rs4300i_I())
      reg.r[rs4300i_RT()] = 1;
   else
      reg.r[rs4300i_RT()] = 0;

}



static void rs4300i_sltiu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sltiu   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%lu)", rs4300i_RT(), rs4300i_RS(), rs4300i_I(), rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   if((DWORD)reg.r[rs4300i_RS()] < (DWORD)rs4300i_I())
      reg.r[rs4300i_RT()] = 1;
   else
      reg.r[rs4300i_RT()] = 0;

}



static void rs4300i_andi()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("andi    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%04hx (%hu)", rs4300i_RT(), rs4300i_RS(), (HWORD)rs4300i_I(), (HWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RT()] = reg.r[rs4300i_RS()] & (HWORD)rs4300i_I();

}



static void rs4300i_ori()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ori     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%04hx (%hu)", rs4300i_RT(), rs4300i_RS(), (HWORD)rs4300i_I(), (HWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RT()] = reg.r[rs4300i_RS()] | (HWORD)rs4300i_I();

}



static void rs4300i_xori()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("xori    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%04hx (%hu)", rs4300i_RT(), rs4300i_RS(), (HWORD)rs4300i_I(), (HWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RT()] = reg.r[rs4300i_RS()] ^ (HWORD)rs4300i_I();

}



static void rs4300i_lui()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lui     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%04hx (%hu)", rs4300i_RT(), (HWORD)rs4300i_I(), (HWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = rs4300i_I() << 16;
      
}



static void rs4300i_cop0()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP0_INSTR)
   {
#ifdef DEBUG_XINST
      printf("cop0 instruction:\n");
#endif
   }
#endif

   ((void (*)()) cop0_rs_instruction[rs4300i_RS()])();
}



static void rs4300i_cop1()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP1_INSTR)
   {
#ifdef DEBUG_XINST
      printf(" cop1 instruction:\n");
#endif
   }
#endif

   ((void (*)()) cop1_rs_instruction[rs4300i_RS()])();
}



static void rs4300i_cop2()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_XINST
      printf(" cop2 instruction:\n");
#endif
   }
#endif

   ((void (*)()) cop2_rs_instruction[rs4300i_RS()])();
}



static void rs4300i_beql()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("beql    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%lu)", rs4300i_RS(), rs4300i_RT(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(reg.r[rs4300i_RS()] == reg.r[rs4300i_RT()])
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}



static void rs4300i_bnel()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bnel    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%08lx (%lu)", rs4300i_RS(), rs4300i_RT(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(reg.r[rs4300i_RS()] != reg.r[rs4300i_RT()])
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}



static void rs4300i_blezl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("blezl   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) <= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}



static void rs4300i_bgtzl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgtzl   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) > 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}





static void rs4300i_daddi()
{
        sDWORD x, y, z;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("daddi   :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u, 0x%05lx (%ld)", rs4300i_RT(), rs4300i_RS(), rs4300i_I(), rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        x = (sDWORD)reg.r[rs4300i_RS()];
        y = (sDWORD)rs4300i_I();
        
        z = x + y;

        
        
        if( (x>>63) ^ (y>>63) )   /* different sign ? */
                reg.r[rs4300i_RT()] = z;
        else
        {
                if( (x>>63) ^ (z>>63) )   /* different sign ? */
                        reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
                else
                        reg.r[rs4300i_RT()] = z;
        }

}





static void rs4300i_daddiu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("daddiu  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%05lx (%ld)", rs4300i_RT(), rs4300i_RS(), rs4300i_I(), rs4300i_I());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RT()] = reg.r[rs4300i_RS()] + rs4300i_I();

}





static void rs4300i_ldl()
{
        WORD    offset;
        DWORD   data;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("ldl     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        offset = reg.r[rs4300i_RS()] + rs4300i_I();

        data = doReadMemDoubleWord(offset & 0xfffffff8);

        switch(offset % 8)
        {
            case 0:
                reg.r[rs4300i_RT()] = data;
                break;

            case 1:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x00000000000000ffLL) + (data << 8);
                break;

            case 2:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x000000000000ffffLL) + (data << 16);
                break;

            case 3:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x0000000000ffffffLL) + (data << 24);
                break;

            case 4:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x00000000ffffffffLL) + (data << 32);
                break;

            case 5:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x000000ffffffffffLL) + (data << 40);
                break;

            case 6:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x0000ffffffffffffLL) + (data << 48);
                break;

            case 7:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0x00ffffffffffffffLL) + (data << 56);
                break;

        } /* switch(offset % 8) */



        // tlb miss exception
        // tlb invalid exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_ldr()
{
        WORD    offset;
        DWORD   data;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("ldr     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        offset = reg.r[rs4300i_RS()] + rs4300i_I();

        data = doReadMemDoubleWord(offset & 0xfffffff8);

        switch(offset % 8)
        {
            case 7:
                reg.r[rs4300i_RT()] = data;
                break;

            case 6:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xff00000000000000LL) + (data >> 8);
                break;

            case 5:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffff000000000000LL) + (data >> 16);
                break;

            case 4:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffff0000000000LL) + (data >> 24);
                break;

            case 3:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffffff00000000LL) + (data >> 32);
                break;

            case 2:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffffffff000000LL) + (data >> 40);
                break;

            case 1:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffffffffff0000LL) + (data >> 48);
                break;

            case 0:
                reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffffffffffff00LL) + (data >> 56);
                break;

        } /* switch(offset % 8) */



        // tlb miss exception
        // tlb invalid exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_lb()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lb      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((sBYTE)doReadMemByte(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception
      
}



static void rs4300i_lh()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lh      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((sHWORD)doReadMemHalfWord(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception
      
}



static void rs4300i_lwl()
{
   DWORD offset;
   WORD  data;

#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lwl     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   offset = (DWORD)(reg.r[rs4300i_RS()] + rs4300i_I());

   data = doReadMemWord(offset & 0xfffffffc);
   
   switch(offset % 4)
   {
      case 0:
         reg.r[rs4300i_RT()] = (sDWORD)(sWORD)data;
         break;

      case 1:
         reg.r[rs4300i_RT()]  = (sDWORD)(sWORD)((reg.r[rs4300i_RT()] & 0x000000ff) + (data << 8));
         break;

      case 2:
         reg.r[rs4300i_RT()]  = (sDWORD)(sWORD)((reg.r[rs4300i_RT()] & 0x0000ffff) + (data << 16));
         break;

      case 3:
         reg.r[rs4300i_RT()]  = (sDWORD)(sWORD)((reg.r[rs4300i_RT()] & 0x00ffffff) + (data << 24));
         break;
   }

   // exception
      
   //reg.halt = 1;
}



static void rs4300i_lw()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lw      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception
      
}



static void rs4300i_lbu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lbu     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((BYTE)doReadMemByte(reg.r[rs4300i_RS()] + rs4300i_I()));

}



static void rs4300i_lhu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lhu     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((HWORD)doReadMemHalfWord(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception

}



static void rs4300i_lwr()
{
   DWORD offset;
   WORD  data;

#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lwr     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   offset = (DWORD)(reg.r[rs4300i_RS()] + rs4300i_I());

   data = doReadMemWord(offset & 0xfffffffc);
   
   switch(offset % 4)
   {
      case 0:
         reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffffff00) + (data >> 24);
         break;

      case 1:
         reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xffff0000) + (data >> 16);
         break;

      case 2:
         reg.r[rs4300i_RT()]  = (reg.r[rs4300i_RT()] & 0xff000000) + (data >> 8);
         break;

      case 3:
         reg.r[rs4300i_RT()]  = (sDWORD)(sWORD)data;
         break;
   }

   // exception
      
   //reg.halt = 1;
}



static void rs4300i_lwu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lwu     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = (sDWORD)((WORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception
      
}



static void rs4300i_sb()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sb      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemByte((BYTE)reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
      
}



static void rs4300i_sh()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sh      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemHalfWord((HWORD)reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
      
}



static void rs4300i_swl()
{
   DWORD offset;
   WORD  data;
   WORD  old_data;

#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("swl     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   offset = (DWORD)reg.r[rs4300i_RS()] + rs4300i_I();
   
   old_data = doReadMemWord(offset & 0xfffffffc);
   
   switch(offset % 4)
   {
      case 0:
         data = (WORD)reg.r[rs4300i_RT()];
         break;

      case 1:
         data = (old_data & 0xff000000) + ((WORD)reg.r[rs4300i_RT()] >> 8);
         break;

      case 2:
         data = (old_data & 0xffff0000) + ((WORD)reg.r[rs4300i_RT()] >> 16);
         break;

      case 3:
         data = (old_data & 0xffffff00) + ((WORD)reg.r[rs4300i_RT()] >> 24);
         break;

      default:
         data = 0;   /* to make compiler happy */
   }

   doWriteMemWord(data, offset & 0xfffffffc);

   // exception
   
   //reg.halt = 1;
      
}



static void rs4300i_sw()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sw      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemWord((WORD)reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
      
}





static void rs4300i_sdl()
{
        WORD    offset;
        DWORD   data;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("sdl     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        offset = reg.r[rs4300i_RS()] + rs4300i_I();

        data = doReadMemDoubleWord(offset & 0xfffffff8);

        switch(offset % 8)
        {
            case 0:
                doWriteMemDoubleWord(reg.r[rs4300i_RT()], offset & 0xfffffff8);
                break;

            case 1:
                doWriteMemDoubleWord((data & 0xff00000000000000LL) + (reg.r[rs4300i_RT()] >> 8), offset & 0xfffffff8);
                break;

            case 2:
                doWriteMemDoubleWord((data & 0xffff000000000000LL) + (reg.r[rs4300i_RT()] >> 16), offset & 0xfffffff8);
                break;

            case 3:
                doWriteMemDoubleWord((data & 0xffffff0000000000LL) + (reg.r[rs4300i_RT()] >> 24), offset & 0xfffffff8);
                break;

            case 4:
                doWriteMemDoubleWord((data & 0xffffffff00000000LL) + (reg.r[rs4300i_RT()] >> 32), offset & 0xfffffff8);
                break;

            case 5:
                doWriteMemDoubleWord((data & 0xffffffffff000000LL) + (reg.r[rs4300i_RT()] >> 40), offset & 0xfffffff8);
                break;

            case 6:
                doWriteMemDoubleWord((data & 0xffffffffffff0000LL) + (reg.r[rs4300i_RT()] >> 48), offset & 0xfffffff8);
                break;

            case 7:
                doWriteMemDoubleWord((data & 0xffffffffffffff00LL) + (reg.r[rs4300i_RT()] >> 56), offset & 0xfffffff8);
                break;

        } /* switch(offset % 8) */



        // tlb miss exception
        // tlb invalid exception
        // tlb modification exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_sdr()
{
        WORD    offset;
        DWORD   data;



#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("sdr     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        offset = reg.r[rs4300i_RS()] + rs4300i_I();

        data = doReadMemDoubleWord(offset & 0xfffffff8);

        switch(offset % 8)
        {
            case 7:
                doWriteMemDoubleWord(reg.r[rs4300i_RT()], offset & 0xfffffff8);
                break;

            case 6:
                doWriteMemDoubleWord((data & 0x00000000000000ffLL) + (reg.r[rs4300i_RT()] << 8), offset & 0xfffffff8);
                break;

            case 5:
                doWriteMemDoubleWord((data & 0x000000000000ffffLL) + (reg.r[rs4300i_RT()] << 16), offset & 0xfffffff8);
                break;

            case 4:
                doWriteMemDoubleWord((data & 0x0000000000ffffffLL) + (reg.r[rs4300i_RT()] << 24), offset & 0xfffffff8);
                break;

            case 3:
                doWriteMemDoubleWord((data & 0x00000000ffffffffLL) + (reg.r[rs4300i_RT()] << 32), offset & 0xfffffff8);
                break;

            case 2:
                doWriteMemDoubleWord((data & 0x000000ffffffffffLL) + (reg.r[rs4300i_RT()] << 40), offset & 0xfffffff8);
                break;

            case 1:
                doWriteMemDoubleWord((data & 0x0000ffffffffffffLL) + (reg.r[rs4300i_RT()] << 48), offset & 0xfffffff8);
                break;

            case 0:
                doWriteMemDoubleWord((data & 0x00ffffffffffffffLL) + (reg.r[rs4300i_RT()] << 56), offset & 0xfffffff8);
                break;

        } /* switch(offset % 8) */



        // tlb miss exception
        // tlb invalid exception
        // tlb modification exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_swr()
{
   DWORD offset;
   WORD  data;
   WORD  old_data;

#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("swr     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   offset = (DWORD)reg.r[rs4300i_RS()] + rs4300i_I();
   
   old_data = doReadMemWord(offset & 0xfffffffc);
   
   switch(offset % 4)
   {
      case 0:
         data = (old_data & 0x00ffffff) + ((WORD)reg.r[rs4300i_RT()] << 24);
         break;

      case 1:
         data = (old_data & 0x0000ffff) + ((WORD)reg.r[rs4300i_RT()] << 16);
         break;

      case 2:
         data = (old_data & 0x000000ff) + ((WORD)reg.r[rs4300i_RT()] << 8);
         break;

      case 3:
         data = (WORD)reg.r[rs4300i_RT()];
         break;

      default:
         data = 0;   /* to make compiler happy */
   }

   doWriteMemWord(data, offset & 0xfffffffc);

   // exception
      
   //reg.halt = 1;
}



static void rs4300i_cache()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_XINST
      printf("cache (NOT IMPLEMENTED - JUST IGNORED):\n");
#endif
   }
#endif
}





static void rs4300i_ll()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("ll      :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        reg.r[rs4300i_RT()] = (sDWORD)(sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I());

        reg.cpr[0][LLADDR] = (sDWORD)(sWORD)(reg.r[rs4300i_RS()] + rs4300i_I());

        reg.llbit = 1;



        // tlb miss exception
        // tlb invalid exception
        // bus error exception
        // address error exception

}





static void rs4300i_lwc1()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CP1_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("lwc1    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" f%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
                printf(" : (f%02u=0x%016llx)", rs4300i_RT(), (sDWORD)((sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I())));
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        reg.cpr[1][__ft] = (sDWORD)((sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));

        // exception
      
}





static void rs4300i_lwc2()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("lwc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" v%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
      printf(" : (v%02u=0x%016llx)", rs4300i_RT(), (sDWORD)((sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I())));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.cpr[2][rs4300i_RT()] = (sDWORD)((sWORD)doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));

   // exception
      
}





static void rs4300i_lld()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("lld     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        reg.r[rs4300i_RT()] = doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I());

        reg.cpr[0][LLADDR] = (sDWORD)(sWORD)(reg.r[rs4300i_RS()] + rs4300i_I());

        reg.llbit = 1;



        // tlb miss exception
        // tlb invalid exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_ldc1()
{
        DWORD value;



#ifdef DEBUG
        if(prefs.debug & DBG_CP1_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("ldc1    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" f%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        
        value = doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I());
        
        if(reg.cpr[0][STATUS] & 0x04000000)
        {
                reg.cpr[1][__ft] = value;
        }
        else
        {
                reg.cpr[1][__ft+0] = (sDWORD)(sWORD)value;
                reg.cpr[1][__ft+1] = (sDWORD)(sWORD)(value >> 32);
        }

        // exception
      
}





static void rs4300i_ldc2()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ldc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" f%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
      printf(" : (f%02u=0x%016llx)", rs4300i_RT(), doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I()));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.cpr[2][rs4300i_RT()] = doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
}



static void rs4300i_ld()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ld      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RT()] = doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
      
}





static void rs4300i_sc()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("scd     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        if(reg.llbit)
        {
                doWriteMemWord((WORD)reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());
        
        } /* if(reg.llbit) */

        reg.r[rs4300i_RT()] = (sDWORD)(sBYTE)reg.llbit;



        // tlb miss exception
        // tlb invalid exception
        // tlb modification exception
        // bus error exception
        // address error exception

}





static void rs4300i_swc1()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CP1_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("swc1    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" f%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
                printf(" : ([0x%08lx]=0x%08lx)", (WORD)reg.r[rs4300i_RS()] + rs4300i_I(), doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        doWriteMemWord(reg.cpr[1][__ft], reg.r[rs4300i_RS()] + rs4300i_I());

        // exception

}





static void rs4300i_swc2()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("swc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" v%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
      printf(" : ([0x%08lx]=0x%08lx)", (WORD)reg.r[rs4300i_RS()] + rs4300i_I(), doReadMemWord(reg.r[rs4300i_RS()] + rs4300i_I()));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemWord(reg.cpr[2][rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception

}





static void rs4300i_scd()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("scd     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif



        if(reg.llbit)
        {
                doWriteMemDoubleWord(reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());
        
        } /* if(reg.llbit) */

        reg.r[rs4300i_RT()] = (sDWORD)(sBYTE)reg.llbit;



        // tlb miss exception
        // tlb invalid exception
        // tlb modification exception
        // bus error exception
        // address error exception
        // reserved instruction exception (vr4300 in 32-bit user or supervisor mode)

}





static void rs4300i_sdc1()
{
        DWORD value;



#ifdef DEBUG
        if(prefs.debug & DBG_CP1_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("sdc1    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" f%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
                printf(" : ([0x%08lx]=0x%016llx)", (WORD)reg.r[rs4300i_RS()] + rs4300i_I(), doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I()));
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if(reg.cpr[0][STATUS] & 0x04000000)
                value = reg.cpr[1][__ft];
        else
                value = (reg.cpr[1][__ft+1] << 32) + reg.cpr[1][__ft+0];
        
        doWriteMemDoubleWord(value, reg.r[rs4300i_RS()] + rs4300i_I());

        // exception

}





static void rs4300i_sdc2()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CP2_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sdc2    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" cpr[2][%02u], 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
      printf(" : ([0x%08lx]=0x%016llx)", (WORD)reg.r[rs4300i_RS()] + rs4300i_I(), doReadMemDoubleWord(reg.r[rs4300i_RS()] + rs4300i_I()));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemDoubleWord(reg.cpr[2][rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception

}



static void rs4300i_sd()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sd      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%05lx(r%02u)", rs4300i_RT(), rs4300i_I(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   doWriteMemDoubleWord(reg.r[rs4300i_RT()], reg.r[rs4300i_RS()] + rs4300i_I());

   // exception
      
}



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

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



// 64 cpu special instructions

static void rs4300i_special_sll()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sll     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)(((WORD)reg.r[rs4300i_RT()]) << rs4300i_SA());

}



static void rs4300i_special_srl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("srl     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)(sWORD)((WORD)reg.r[rs4300i_RT()] >> rs4300i_SA());

}



static void rs4300i_special_sra()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sra     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)((sWORD)reg.r[rs4300i_RT()] >> rs4300i_SA());

}



static void rs4300i_special_sllv()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sllv    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)((sWORD)((reg.r[rs4300i_RT()]) << (reg.r[rs4300i_RS()] & 0x1f)));

}



static void rs4300i_special_srlv()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("srlv    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)(sWORD)((WORD)reg.r[rs4300i_RT()] >> (reg.r[rs4300i_RS()] & 0x1f));

}



static void rs4300i_special_srav()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("srav    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[rs4300i_RD()] = (sDWORD)((sWORD)reg.r[rs4300i_RT()] >> (reg.r[rs4300i_RS()] & 0x1f));

}



static void rs4300i_special_jr()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("jr      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u", rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.delay = 1;
   reg.pc_delay = reg.r[rs4300i_RS()];

}



static void rs4300i_special_jalr()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("jalr    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RD(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.delay = 1;
   reg.pc_delay = reg.r[rs4300i_RS()];
   reg.r[rs4300i_RD()] = reg.pc + 8;

}



static void rs4300i_special_syscall()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("syscall :");
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        reg.do_or_check_sthg |= RS4300I_DO_SYSCALL_EXCEPTION;

}



static void rs4300i_special_break()
{
#ifdef DEBUG_NOTIMPLEMENTED
      printf(" break (NOT IMPLEMENTED) \n");
#endif

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



static void rs4300i_special_sync()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_XINST
      printf("sync (NOT IMPLEMENTED - JUST DOES NOTHING):\n");
#endif
   }
#endif
}



static void rs4300i_special_mfhi()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mfhi    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u", rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = reg.hi;
   
}



static void rs4300i_special_mthi()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mthi    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u", rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.hi = reg.r[rs4300i_RS()];
   
}



static void rs4300i_special_mflo()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mflo    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u", rs4300i_RD());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = reg.lo;
   
}



static void rs4300i_special_mtlo()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mtlo    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u", rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.lo = reg.r[rs4300i_RS()];
   
}



static void rs4300i_special_dsllv()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsllv   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] << (reg.r[rs4300i_RS()] & 0x1f);

}



static void rs4300i_special_dsrlv()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsrlv   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = (DWORD)reg.r[rs4300i_RT()] >> (reg.r[rs4300i_RS()] & 0x1f);

}



static void rs4300i_special_dsrav()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsrav   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RT(), rs4300i_RS());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] >> (reg.r[rs4300i_RS()] & 0x1f);

}





static void rs4300i_special_mult()
{
   sDWORD temp;


   
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("mult    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   temp = (sDWORD)((sWORD)reg.r[rs4300i_RS()]) * ((sWORD)reg.r[rs4300i_RT()]);
   reg.lo = (sDWORD)(sWORD)(temp);
   reg.hi = (sDWORD)(sWORD)(temp >> 32);

} /* static void rs4300i_special_mult() */





static void rs4300i_special_multu()
{
   DWORD temp;
   

   
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("multu   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   temp = (DWORD)((WORD)reg.r[rs4300i_RS()]) * ((WORD)reg.r[rs4300i_RT()]);
   reg.lo = (sDWORD)(sWORD)(temp);
   reg.hi = (sDWORD)(sWORD)(temp >> 32);

} /* static void rs4300i_special_multu() */





static void rs4300i_special_div()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("div     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if((sWORD)reg.r[rs4300i_RT()] != 0)
   {
      reg.lo = (sDWORD)(sWORD)((sWORD)reg.r[rs4300i_RS()] / (sWORD)reg.r[rs4300i_RT()]);
      reg.hi = (sDWORD)(sWORD)((sWORD)reg.r[rs4300i_RS()] % (sWORD)reg.r[rs4300i_RT()]);
   }

} /* static void rs4300i_special_div() */





static void rs4300i_special_divu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("divu    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if((WORD)reg.r[rs4300i_RT()] != 0)
   {
      reg.lo = (sDWORD)(sWORD)((WORD)reg.r[rs4300i_RS()] / (WORD)reg.r[rs4300i_RT()]);
      reg.hi = (sDWORD)(sWORD)((WORD)reg.r[rs4300i_RS()] % (WORD)reg.r[rs4300i_RT()]);
   }

} /* static void rs4300i_special_divu() */





static void rs4300i_special_dmult()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dmult   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   // reserved instruction exception (in 32bit mode)
   reg.lo = reg.r[rs4300i_RS()] * reg.r[rs4300i_RT()];
   reg.hi = 0;

} /* static void rs4300i_special_dmult() */





static void rs4300i_special_dmultu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dmultu  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   // reserved instruction exception (in 32bit mode)
   reg.lo = (DWORD)reg.r[rs4300i_RS()] * (DWORD)reg.r[rs4300i_RT()];
   reg.hi = 0;

} /* static void rs4300i_special_dmultu() */





static void rs4300i_special_ddiv()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ddiv    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   if(reg.r[rs4300i_RT()] != 0)
   {
      reg.lo = reg.r[rs4300i_RS()] / reg.r[rs4300i_RT()];
      reg.hi = reg.r[rs4300i_RS()] % reg.r[rs4300i_RT()];
   }

} /* static void rs4300i_special_ddiv() */





static void rs4300i_special_ddivu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("ddivu   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   // reserved instruction exception (in 32bit mode)
   if((DWORD)reg.r[rs4300i_RT()] != 0)
   {
      reg.lo = (DWORD)reg.r[rs4300i_RS()] / (DWORD)reg.r[rs4300i_RT()];
      reg.hi = (DWORD)reg.r[rs4300i_RS()] % (DWORD)reg.r[rs4300i_RT()];
   }

} /* static void rs4300i_special_ddivu() */





static void rs4300i_special_add()
{
        sDWORD x, y, z;



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


        x = (sWORD)reg.r[rs4300i_RS()];
        y = (sWORD)reg.r[rs4300i_RT()];
        
        z = x + y;

        
        
        if((z > 0x7fffffffLL) || (z < -0x80000000LL))
                reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
        else
                reg.r[rs4300i_RD()] = (sDWORD)(sWORD)z;

}





static void rs4300i_special_addu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("addu    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = (sDWORD)(sWORD)(reg.r[rs4300i_RS()] + reg.r[rs4300i_RT()]);

}



static void rs4300i_special_sub()
{
        sDWORD x, y, z;



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


        x = (sWORD)reg.r[rs4300i_RS()];
        y = (sWORD)reg.r[rs4300i_RT()];
        
        z = x - y;

        
        
        if((z > 0x7fffffffLL) || (z < -0x80000000LL))
                reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
        else
                reg.r[rs4300i_RD()] = (sDWORD)(sWORD)z;

}



static void rs4300i_special_subu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("subu    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = (sDWORD)((sWORD)reg.r[rs4300i_RS()] - (sWORD)reg.r[rs4300i_RT()]);

}



static void rs4300i_special_and()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("and     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = reg.r[rs4300i_RS()] & reg.r[rs4300i_RT()];

}



static void rs4300i_special_or()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("or      :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = reg.r[rs4300i_RS()] | reg.r[rs4300i_RT()];

}



static void rs4300i_special_xor()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("xor     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = reg.r[rs4300i_RS()] ^ reg.r[rs4300i_RT()];

}



static void rs4300i_special_nor()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("nor     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   reg.r[rs4300i_RD()] = ~(reg.r[rs4300i_RS()] | reg.r[rs4300i_RT()]);
}



static void rs4300i_special_slt()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("slt     :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   if(reg.r[rs4300i_RS()] < reg.r[rs4300i_RT()])
      reg.r[rs4300i_RD()] = 1;
   else
      reg.r[rs4300i_RD()] = 0;

}



static void rs4300i_special_sltu()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("sltu    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif


   if((DWORD)reg.r[rs4300i_RS()] < (DWORD)reg.r[rs4300i_RT()])
      reg.r[rs4300i_RD()] = 1;
   else
      reg.r[rs4300i_RD()] = 0;

}





static void rs4300i_special_dadd()
{
        sDWORD x, y, z;



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


        // reserved instruction exception (in 32bit mode)
        
        x = (sDWORD)reg.r[rs4300i_RS()];
        y = (sDWORD)reg.r[rs4300i_RT()];
        
        z = x + y;

        
        
        if( (x>>63) ^ (y>>63) )   /* different sign ? */
                reg.r[rs4300i_RD()] = z;
        else
        {
                if( (x>>63) ^ (z>>63) )   /* different sign ? */
                        reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
                else
                        reg.r[rs4300i_RD()] = z;
        }

}





static void rs4300i_special_daddu()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("daddu   :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u, r%02u", rs4300i_RD(), rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        // reserved instruction exception (in 32bit mode)

        reg.r[rs4300i_RD()] = reg.r[rs4300i_RS()] + reg.r[rs4300i_RT()];

}



static void rs4300i_special_dsub()
{
        sDWORD x, y, z;



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



        // reserved instruction exception (in 32bit mode)
        
        x = (sDWORD)reg.r[rs4300i_RS()];
        y = (sDWORD)reg.r[rs4300i_RT()];
        
        z = x - y;

        
        
        if( (x>>63) ^ (y>>63) )   /* different sign ? */
        {
                if( (x>>63) ^ (z>>63) )   /* different sign ? */
                        reg.do_or_check_sthg = RS4300I_DO_INTEGER_OVERFLOW_EXCEPTION;
                else
                        reg.r[rs4300i_RD()] = z;
        }
        else
                reg.r[rs4300i_RD()] = z;

}





static void rs4300i_special_dsubu()
{
   sDWORD temp;

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


   // reserved instruction exception (in 32bit mode)
   temp = reg.r[rs4300i_RS()] - reg.r[rs4300i_RT()];
   reg.r[rs4300i_RD()] = temp;

}





static void rs4300i_special_tge()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tge     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if((sDWORD)reg.r[rs4300i_RS()] >= (sDWORD)reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_special_tgeu()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tgeu    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if((DWORD)reg.r[rs4300i_RS()] >= (DWORD)reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_special_tlt()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tlt     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if((sDWORD)reg.r[rs4300i_RS()] < (sDWORD)reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_special_tltu()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tltu    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if((DWORD)reg.r[rs4300i_RS()] < (DWORD)reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
}

}





static void rs4300i_special_teq()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("teq     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if(reg.r[rs4300i_RS()] == reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_special_tne()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tne     :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, r%02u", rs4300i_RS(), rs4300i_RT());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif

        if(reg.r[rs4300i_RS()] != reg.r[rs4300i_RT()])
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_special_dsll()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsll    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] << rs4300i_SA();

}



static void rs4300i_special_dsrl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsrl    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = (DWORD)reg.r[rs4300i_RT()] >> rs4300i_SA();

}



static void rs4300i_special_dsra()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsra    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] >> rs4300i_SA();

}



static void rs4300i_special_dsll32()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsll32  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] << (32 + rs4300i_SA());

}



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

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



static void rs4300i_special_dsrl32()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsra32  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = (DWORD)reg.r[rs4300i_RT()] >> (32 + rs4300i_SA());

}



static void rs4300i_special_dsra32()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("dsra32  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, r%02u, 0x%02x (%u)", rs4300i_RD(), rs4300i_RT(), rs4300i_SA(), rs4300i_SA());
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   // reserved instruction exception (in 32bit mode)
   reg.r[rs4300i_RD()] = reg.r[rs4300i_RT()] >> (32 + rs4300i_SA());

}




// 32 cpu regimm instructions

static void rs4300i_regimm_bltz()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bltz    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) < 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }

}

static void rs4300i_regimm_bgez()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgez    :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) >= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }

}

static void rs4300i_regimm_bltzl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bltzl   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) < 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}

static void rs4300i_regimm_bgezl()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgezl   :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   if(((sDWORD)reg.r[rs4300i_RS()]) >= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}





static void rs4300i_regimm_tgei()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tgei    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llxx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if((sDWORD)reg.r[rs4300i_RS()] >= (sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_tgeiu()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tgeiu   :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if((DWORD)reg.r[rs4300i_RS()] >= (DWORD)(sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_tlti()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tlti    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if((sDWORD)reg.r[rs4300i_RS()] < (sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_tltiu()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tltiu   :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if((DWORD)reg.r[rs4300i_RS()] < (DWORD)(sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_teqi()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("teqi    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sHWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if(reg.r[rs4300i_RS()] == (sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_tnei()
{
#ifdef DEBUG
        if(prefs.debug & DBG_CPU_INSTR)
        {
#ifdef DEBUG_OPCODE
                printf("tnei    :");
#endif
#ifdef DEBUG_MNEMONIC
                printf(" r%02u, 0x%016llx (%lld)", rs4300i_RS(), (sDWORD)(sWORD)rs4300i_I(), (sDWORD)(sWORD)rs4300i_I());
#endif
#ifdef DEBUG_INST
                printf("\n");
#endif
        }
#endif


        if(reg.r[rs4300i_RS()] != (DWORD)(sDWORD)(sWORD)rs4300i_I())
        {
                reg.do_or_check_sthg |= RS4300I_DO_TRAP_EXCEPTION;
        }

}





static void rs4300i_regimm_bltzal()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bltzal  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[31] = reg.pc + 8;

   if(((sDWORD)reg.r[rs4300i_RS()]) < 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }

}

static void rs4300i_regimm_bgezal()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgezal  :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[31] = reg.pc + 8;

   if(((sDWORD)reg.r[rs4300i_RS()]) >= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }

}

static void rs4300i_regimm_bltzall()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bltzall :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[31] = reg.pc + 8;

   if(((sDWORD)reg.r[rs4300i_RS()]) < 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}

static void rs4300i_regimm_bgezall()
{
#ifdef DEBUG
   if(prefs.debug & DBG_CPU_INSTR)
   {
#ifdef DEBUG_OPCODE
      printf("bgezall :");
#endif
#ifdef DEBUG_MNEMONIC
      printf(" r%02u, 0x%08lx (%lu)", rs4300i_RS(), reg.pc + 4 + (rs4300i_I() << 2), reg.pc + 4 + (rs4300i_I() << 2));
#endif
#ifdef DEBUG_INST
      printf("\n");
#endif
   }
#endif

   reg.r[31] = reg.pc + 8;

   if(((sDWORD)reg.r[rs4300i_RS()]) >= 0)
   {
      reg.delay = 1;
      reg.pc_delay = reg.pc + 4 + (rs4300i_I() << 2);
   }
   else
      reg.pc += 4;

}

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

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





