Beispiel #1
0
void BGEZALL_OUT(void)
{
   local_rs = irs;
   reg[31]=PC->addr+8;
   if((&irs)!=(reg+31))
     {
    if (local_rs >= 0)
      {
         jump_target = (int)PC->f.i.immediate;
         PC++;
         delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
         PC->ops();
         update_count();
         delay_slot=0;
         if (!skip_jump)
           jump_to(PC->addr + ((jump_target-1)<<2));
      }
    else
      PC+=2;
     }
   else DebugMessage(M64MSG_ERROR, "error in BGEZALL_OUT");
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #2
0
void BGEZALL_OUT(void)
{
    local_rs = irs;
    reg[31]=PC->addr+8;
    if((&irs)!=(reg+31))
    {
        if (local_rs >= 0)
        {
            jump_target = (int)PC->f.i.immediate;
            PC++;
            delay_slot=1;
#ifdef DBG
            if (debugger_mode) update_debugger(PC->addr);
#endif
            PC->ops();
            update_count();
            delay_slot=0;
            if (!skip_jump)
                jump_to(PC->addr + ((jump_target-1)<<2));
        }
        else
            PC+=2;
    }
    else printf("erreur dans bgezall\n");
    last_addr = PC->addr;
    if (next_interupt <= Count) gen_interupt();
}
Beispiel #3
0
void BLTZALL(void)
{
   local_rs = irs;
   reg[31]=PC->addr+8;
   if((&irs)!=(reg+31))
     {
    if (local_rs < 0)
      {
         PC++;
         delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
         PC->ops();
         update_count();
         delay_slot=0;
         if(!skip_jump)
           PC += (PC-2)->f.i.immediate-1;
      }
    else
      PC+=2;
     }
   else DebugMessage(M64MSG_ERROR, "error in BLTZALL");
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
int write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
{
    struct r4300_core* r4300 = (struct r4300_core*)opaque;
    uint32_t reg = mi_reg(address);
    const uint32_t* cp0_regs = r4300_cp0_regs();

    switch(reg)
    {
    case MI_INIT_MODE_REG:
        if (update_mi_init_mode(&r4300->mi.regs[MI_INIT_MODE_REG], value & mask) != 0)
        {
            clear_rcp_interrupt(r4300, MI_INTR_DP);
        }
        break;
    case MI_INTR_MASK_REG:
        update_mi_intr_mask(&r4300->mi.regs[MI_INTR_MASK_REG], value & mask);

        check_interupt();
        cp0_update_count();
        if (next_interupt <= cp0_regs[CP0_COUNT_REG]) gen_interupt();
        break;
    }

    return 0;
}
Beispiel #5
0
void BLTZALL(void)
{
    local_rs = irs;
    reg[31]=PC->addr+8;
    if((&irs)!=(reg+31))
    {
        if (local_rs < 0)
        {
            PC++;
            delay_slot=1;
#ifdef DBG
            if (debugger_mode) update_debugger(PC->addr);
#endif
            PC->ops();
            update_count();
            delay_slot=0;
            if(!skip_jump)
                PC += (PC-2)->f.i.immediate-1;
        }
        else
            PC+=2;
    }
    else printf("erreur dans bltzall\n");
    last_addr = PC->addr;
    if (next_interupt <= Count) gen_interupt();
}
Beispiel #6
0
void J()
{
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump)
     PC=actual->block+
     (((((PC-2)->f.j.inst_index<<2) | ((PC-1)->addr & 0xF0000000))-actual->start)>>2);
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #7
0
void J_OUT()
{
   jump_target = (PC->addr & 0xF0000000) | (PC->f.j.inst_index<<2);
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump)
     jump_to(jump_target);
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #8
0
void BGEZ()
{
   local_rs = irs;
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if (local_rs >= 0 && !skip_jump)
     PC += (PC-2)->f.i.immediate - 1;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #9
0
void BC1T()
{
   if (check_cop1_unusable()) return;
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if ((FCR31 & 0x800000)!=0 && !skip_jump)
     PC += (PC-2)->f.i.immediate-1;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #10
0
void BC1T_OUT()
{
   if (check_cop1_unusable()) return;
   jump_target = (long)PC->f.i.immediate;
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump && (FCR31 & 0x800000)!=0)
     jump_to(PC->addr + ((jump_target-1)<<2));
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #11
0
void BGEZ_OUT()
{
   local_rs = irs;
   jump_target = (long)PC->f.i.immediate;
   PC++;
   delay_slot=1;
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump && local_rs >= 0)
     jump_to(PC->addr + ((jump_target-1)<<2));
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #12
0
void J_OUT(void)
{
   jump_target = (PC->addr & 0xF0000000) | (PC->f.j.inst_index<<2);
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump)
     jump_to(jump_target);
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #13
0
void BGEZ(void)
{
   local_rs = irs;
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if (local_rs >= 0 && !skip_jump)
     PC += (PC-2)->f.i.immediate - 1;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #14
0
void BC1T(void)
{
   if (check_cop1_unusable()) return;
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if ((FCR31 & 0x800000)!=0 && !skip_jump)
     PC += (PC-2)->f.i.immediate-1;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #15
0
void J(void)
{
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump)
     PC=actual->block+
     (((((PC-2)->f.j.inst_index<<2) | ((PC-1)->addr & 0xF0000000))-actual->start)>>2);
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #16
0
void BC1T_OUT(void)
{
   if (check_cop1_unusable()) return;
   jump_target = (int)PC->f.i.immediate;
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump && (FCR31 & 0x800000)!=0)
     jump_to(PC->addr + ((jump_target-1)<<2));
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #17
0
void BGEZL()
{
   if (irs >= 0)
     {
	PC++;
	delay_slot=1;
	PC->ops();
	update_count();
	delay_slot=0;
	if(!skip_jump)
	  PC += (PC-2)->f.i.immediate-1;
     }
   else
     PC+=2;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #18
0
void BLTZ_OUT(void)
{
   local_rs = irs;
   jump_target = (int)PC->f.i.immediate;
   PC++;
   delay_slot=1;
#ifdef DBG
            if (g_DebuggerActive) update_debugger(PC->addr);
#endif
   PC->ops();
   update_count();
   delay_slot=0;
   if (!skip_jump && local_rs < 0)
     jump_to(PC->addr + ((jump_target-1)<<2));
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #19
0
void BGEZAL()
{
   local_rs = irs;
   reg[31]=PC->addr+8;
   if((&irs)!=(long long int *)(reg+31))
     {
	PC++;
	delay_slot=1;
	PC->ops();
	update_count();
	delay_slot=0;
	if(local_rs >= 0 && !skip_jump)
	  PC += (PC-2)->f.i.immediate-1;
     }
   else printf("erreur dans bgezal\n");
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #20
0
void BGEZL_OUT()
{
   if (irs >= 0)
     {
	jump_target = (long)PC->f.i.immediate;
	PC++;
	delay_slot=1;
	PC->ops();
	update_count();
	delay_slot=0;
	if (!skip_jump)
	  jump_to(PC->addr + ((jump_target-1)<<2));
     }
   else
     PC+=2;
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #21
0
void BGEZAL_OUT()
{
   local_rs = irs;
   reg[31]=PC->addr+8;
   if((&irs)!=(long long int *)(reg+31))
     {
	jump_target = (long)PC->f.i.immediate;
	PC++;
	delay_slot=1;
	PC->ops();
	update_count();
	delay_slot=0;
	if(!skip_jump && local_rs >= 0)
	  jump_to(PC->addr + ((jump_target-1)<<2));
     }
   else printf("erreur dans bgezal\n");
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #22
0
void BGEZL(void)
{
    if (irs >= 0)
    {
        PC++;
        delay_slot=1;
#ifdef DBG
        if (debugger_mode) update_debugger(PC->addr);
#endif
        PC->ops();
        update_count();
        delay_slot=0;
        if(!skip_jump)
            PC += (PC-2)->f.i.immediate-1;
    }
    else
        PC+=2;
    last_addr = PC->addr;
    if (next_interupt <= Count) gen_interupt();
}
Beispiel #23
0
void BGEZL_OUT(void)
{
    if (irs >= 0)
    {
        jump_target = (int)PC->f.i.immediate;
        PC++;
        delay_slot=1;
#ifdef DBG
        if (debugger_mode) update_debugger(PC->addr);
#endif
        PC->ops();
        update_count();
        delay_slot=0;
        if (!skip_jump)
            jump_to(PC->addr + ((jump_target-1)<<2));
    }
    else
        PC+=2;
    last_addr = PC->addr;
    if (next_interupt <= Count) gen_interupt();
}
Beispiel #24
0
void BC1TL(void)
{
   if (check_cop1_unusable()) return;
   if ((FCR31 & 0x800000)!=0)
     {
    PC++;
    delay_slot=1;
#ifdef DBG
            if (debugger_mode) update_debugger(PC->addr);
#endif
    PC->ops();
    update_count();
    delay_slot=0;
    if(!skip_jump)
      PC += (PC-2)->f.i.immediate-1;
     }
   else {
     PC+=2;
     update_count();
  }
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #25
0
void BC1FL_OUT(void)
{
   if (check_cop1_unusable()) return;
   if ((FCR31 & 0x800000)==0)
     {
    jump_target = (int)PC->f.i.immediate;
    PC++;
    delay_slot=1;
#ifdef DBG
            if (debugger_mode) update_debugger(PC->addr);
#endif
    PC->ops();
    update_count();
    delay_slot=0;
    if (!skip_jump)
      jump_to(PC->addr + ((jump_target-1)<<2));
     }
   else {
     PC+=2;
     update_count();
  }
   last_addr = PC->addr;
   if (next_interupt <= Count) gen_interupt();
}
Beispiel #26
0
void MTC0()
{
   switch(PC->f.r.nrd)
     {
      case 0:    // Index
	Index = rrt & 0x8000003F;
	if ((Index & 0x3F) > 31) 
	  {
	     printf ("il y a plus de 32 TLB\n");
	     stop=1;
	  }
	break;
      case 1:    // Random
	break;
      case 2:    // EntryLo0
	EntryLo0 = rrt & 0x3FFFFFFF;
	break;
      case 3:    // EntryLo1
 	EntryLo1 = rrt & 0x3FFFFFFF;
	break;
      case 4:    // Context
	Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0);
	break;
      case 5:    // PageMask
	PageMask = rrt & 0x01FFE000;
	break;
      case 6:    // Wired
	Wired = rrt;
	Random = 31;
	break;
      case 8:    // BadVAddr
	break;
      case 9:    // Count
	update_count();
	if (next_interupt <= Count) gen_interupt();
	translate_event_queue(rrt & 0xFFFFFFFF);
	Count = rrt & 0xFFFFFFFF;
	break;
      case 10:   // EntryHi
	EntryHi = rrt & 0xFFFFE0FF;
	break;
      case 11:   // Compare
	update_count();
	remove_event(COMPARE_INT);
	add_interupt_event_count(COMPARE_INT, (unsigned long)rrt);
	Compare = rrt;
	Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear
	break;
      case 12:   // Status
	if((rrt & 0x04000000) != (Status & 0x04000000))
	  {
	     shuffle_fpr_data(Status, rrt);
	     set_fpr_pointers(rrt);
	  }
	Status = rrt;
	update_count();
	PC++;
	check_interupt();
	if (next_interupt <= Count) gen_interupt();
	PC--;
	break;
      case 13:   // Cause
	if (rrt!=0)
	  {
	     printf("écriture dans Cause\n");
	     stop = 1;
	  }
	else Cause = rrt;
	break;
      case 14:   // EPC
	EPC = rrt;
	break;
      case 15:  // PRevID
	break;
      case 16:  // Config
	Config = rrt;
	break;
      case 18:  // WatchLo
	WatchLo = rrt & 0xFFFFFFFF;
	break;
      case 19:  // WatchHi
	WatchHi = rrt & 0xFFFFFFFF;
	break;
      case 27:  // CacheErr
	break;
      case 28:  // TagLo
	TagLo = rrt & 0x0FFFFFC0;
	break;
      case 29: // TagHi
	TagHi =0;
	break;
      default:
	printf("unknown mtc0 write : %d\n", PC->f.r.nrd);
	stop=1;
     }
   PC++;
}
Beispiel #27
0
void MTC0()
{
   switch(PC->f.r.nrd)
     {
      case 0:    // Index
	Index = rrt & 0x8000003F;
	if ((Index & 0x3F) > 31) 
	  {
	     printf ("il y a plus de 32 TLB\n");
	     stop=1;
	  }
	break;
      case 1:    // Random
	break;
      case 2:    // EntryLo0
	EntryLo0 = rrt & 0x3FFFFFFF;
	break;
      case 3:    // EntryLo1
 	EntryLo1 = rrt & 0x3FFFFFFF;
	break;
      case 4:    // Context
	Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0);
	break;
      case 5:    // PageMask
	PageMask = rrt & 0x01FFE000;
	break;
      case 6:    // Wired
	Wired = rrt;
	Random = 31;
	break;
      case 8:    // BadVAddr
	break;
      case 9:    // Count
	update_count();
	if (next_interupt <= Count) gen_interupt();
	debug_count += Count;
	translate_event_queue(rrt & 0xFFFFFFFF);
	Count = rrt & 0xFFFFFFFF;
	debug_count -= Count;
	break;
      case 10:   // EntryHi
	EntryHi = rrt & 0xFFFFE0FF;
	break;
      case 11:   // Compare
	update_count();
	remove_event(COMPARE_INT);
	add_interupt_event_count(COMPARE_INT, (unsigned long)rrt);
	Compare = rrt;
	Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear
	break;
      case 12:   // Status
	if((rrt & 0x04000000) != (Status & 0x04000000))
	  {
	     if (rrt & 0x04000000)
	       {
		  int i;
		  for (i=0; i<32; i++)
		    {
		       reg_cop1_double[i]=(double*)&reg_cop1_fgr_64[i];
		       reg_cop1_simple[i]=(float*)&reg_cop1_fgr_64[i];
		    }
	       }
	     else
	       {
		  int i;
		  for (i=0; i<32; i++)
		    {
		       if(!(i&1))
			 reg_cop1_double[i]=(double*)&reg_cop1_fgr_64[i>>1];
#ifndef _BIG_ENDIAN
		       reg_cop1_simple[i]=(float*)&reg_cop1_fgr_64[i>>1]+(i&1);
#else
		       reg_cop1_simple[i]=(float*)&reg_cop1_fgr_64[i>>1]+(1-(i&1));
#endif
		    }
	       }
	  }
	Status = rrt;
	PC++;
	check_interupt();
	update_count();
	if (next_interupt <= Count) gen_interupt();
	PC--;
	break;
      case 13:   // Cause
	if (rrt!=0)
	  {
	     printf("écriture dans Cause\n");
	     stop = 1;
	  }
	else Cause = rrt;
	break;
      case 14:   // EPC
	EPC = rrt;
	break;
      case 15:  // PRevID
	break;
      case 16:  // Config
	Config = rrt;
	break;
      case 18:  // WatchLo
	WatchLo = rrt & 0xFFFFFFFF;
	break;
      case 19:  // WatchHi
	WatchHi = rrt & 0xFFFFFFFF;
	break;
      case 27:  // CacheErr
	break;
      case 28:  // TagLo
	TagLo = rrt & 0x0FFFFFC0;
	break;
      case 29: // TagHi
	TagHi =0;
	break;
      default:
	printf("unknown mtc0 write : %d\n", PC->f.r.nrd);
	stop=1;
     }
   PC++;
}
Beispiel #28
0
void MTC0(void)
{
    switch(PC->f.r.nrd)
    {
    case 0:    // Index
        Index = rrt & 0x8000003F;
        if ((Index & 0x3F) > 31)
        {
            DebugMessage(M64MSG_ERROR, "MTC0 instruction writing Index register with TLB index > 31");
            stop=1;
        }
        break;
    case 1:    // Random
        break;
    case 2:    // EntryLo0
        EntryLo0 = rrt & 0x3FFFFFFF;
        break;
    case 3:    // EntryLo1
        EntryLo1 = rrt & 0x3FFFFFFF;
        break;
    case 4:    // Context
        Context = (rrt & 0xFF800000) | (Context & 0x007FFFF0);
        break;
    case 5:    // PageMask
        PageMask = rrt & 0x01FFE000;
        break;
    case 6:    // Wired
        Wired = rrt;
        Random = 31;
        break;
    case 8:    // BadVAddr
        break;
    case 9:    // Count
        update_count();
        if (next_interupt <= Count) gen_interupt();
        debug_count += Count;
        translate_event_queue(rrt & 0xFFFFFFFF);
        Count = rrt & 0xFFFFFFFF;
        debug_count -= Count;
        break;
    case 10:   // EntryHi
        EntryHi = rrt & 0xFFFFE0FF;
        break;
    case 11:   // Compare
        update_count();
        remove_event(COMPARE_INT);
        add_interupt_event_count(COMPARE_INT, (unsigned int)rrt);
        Compare = rrt;
        Cause = Cause & 0xFFFF7FFF; //Timer interupt is clear
        break;
    case 12:   // Status
        if((rrt & 0x04000000) != (Status & 0x04000000))
        {
            shuffle_fpr_data(Status, rrt);
            set_fpr_pointers(rrt);
        }
        Status = rrt;
        PC++;
        check_interupt();
        update_count();
        if (next_interupt <= Count) gen_interupt();
        PC--;
        break;
    case 13:   // Cause
        if (rrt!=0)
        {
            DebugMessage(M64MSG_ERROR, "MTC0 instruction trying to write Cause register with non-0 value");
            stop = 1;
        }
        else Cause = rrt;
        break;
    case 14:   // EPC
        EPC = rrt;
        break;
    case 15:  // PRevID
        break;
    case 16:  // Config
        Config = rrt;
        break;
    case 18:  // WatchLo
        WatchLo = rrt & 0xFFFFFFFF;
        break;
    case 19:  // WatchHi
        WatchHi = rrt & 0xFFFFFFFF;
        break;
    case 27:  // CacheErr
        break;
    case 28:  // TagLo
        TagLo = rrt & 0x0FFFFFC0;
        break;
    case 29: // TagHi
        TagHi =0;
        break;
    default:
        DebugMessage(M64MSG_ERROR, "Unknown MTC0 write: %d", PC->f.r.nrd);
        stop=1;
    }
    PC++;
}
Beispiel #29
0
void gen_interupt(void)
{
    if (stop == 1)
    {
        vi_counter = 0; // debug
        dyna_stop();
    }

    if (!interupt_unsafe_state)
    {
        if (reset_hard_job)
        {
            reset_hard();
            reset_hard_job = 0;
            return;
        }
    }
   
    if (skip_jump)
    {
        unsigned int dest = skip_jump;
        skip_jump = 0;

        if (q->count > Count || (Count - q->count) < 0x80000000)
            next_interupt = q->count;
        else
            next_interupt = 0;
        
        last_addr = dest;
        generic_jump_to(dest);
        return;
    } 

    switch(q->type)
    {
        case SPECIAL_INT:
            if (Count > 0x10000000) return;
            remove_interupt_event();
            add_interupt_event_count(SPECIAL_INT, 0);
            return;
            break;
        case VI_INT:
            if (retro_return(false) != savestates_job_nothing)
            {
                gen_interupt();
                return;
            }

            gfx.updateScreen();

            refresh_stat();
            if (vi_register.vi_v_sync == 0) vi_register.vi_delay = 500000;
            else vi_register.vi_delay = ((vi_register.vi_v_sync + 1)*1500);
            next_vi += vi_register.vi_delay;
            if (vi_register.vi_status&0x40) vi_field=1-vi_field;
            else vi_field=0;

            remove_interupt_event();
            add_interupt_event_count(VI_INT, next_vi);
    
            MI_register.mi_intr_reg |= 0x08;
            if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                Cause = (Cause | 0x400) & 0xFFFFFF83;
            else
                return;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;
    
        case COMPARE_INT:
            remove_interupt_event();
            Count+=2;
            add_interupt_event_count(COMPARE_INT, Compare);
            Count-=2;
    
            Cause = (Cause | 0x8000) & 0xFFFFFF83;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;
    
        case CHECK_INT:
            remove_interupt_event();
            break;
    
        case SI_INT:
            PIF_RAMb[0x3F] = 0x0;
            remove_interupt_event();
            MI_register.mi_intr_reg |= 0x02;
            si_register.si_stat |= 0x1000;
            //si_register.si_stat &= ~0x1;
            if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                Cause = (Cause | 0x400) & 0xFFFFFF83;
            else
                return;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;
    
        case PI_INT:
            remove_interupt_event();
            MI_register.mi_intr_reg |= 0x10;
            pi_register.read_pi_status_reg &= ~3;
            if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                Cause = (Cause | 0x400) & 0xFFFFFF83;
            else
                return;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;
    
        case AI_INT:
            if (ai_register.ai_status & 0x80000000) // full
            {
                unsigned int ai_event = get_event(AI_INT);
                remove_interupt_event();
                ai_register.ai_status &= ~0x80000000;
                ai_register.current_delay = ai_register.next_delay;
                ai_register.current_len = ai_register.next_len;
                add_interupt_event_count(AI_INT, ai_event+ai_register.next_delay);
         
                MI_register.mi_intr_reg |= 0x04;
                if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                    Cause = (Cause | 0x400) & 0xFFFFFF83;
                else
                    return;
                if ((Status & 7) != 1) return;
                if (!(Status & Cause & 0xFF00)) return;
            }
            else
            {
                remove_interupt_event();
                ai_register.ai_status &= ~0x40000000;

                //-------
                MI_register.mi_intr_reg |= 0x04;
                if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                    Cause = (Cause | 0x400) & 0xFFFFFF83;
                else
                    return;
                if ((Status & 7) != 1) return;
                if (!(Status & Cause & 0xFF00)) return;
            }
            break;

        case SP_INT:
            remove_interupt_event();
            sp_register.sp_status_reg |= 0x203;
            // sp_register.sp_status_reg |= 0x303;
    
            if (!(sp_register.sp_status_reg & 0x40)) return; // !intr_on_break
            MI_register.mi_intr_reg |= 0x01;
            if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                Cause = (Cause | 0x400) & 0xFFFFFF83;
            else
                return;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;
    
        case DP_INT:
            remove_interupt_event();
            dpc_register.dpc_status &= ~2;
            dpc_register.dpc_status |= 0x81;
            MI_register.mi_intr_reg |= 0x20;
            if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
                Cause = (Cause | 0x400) & 0xFFFFFF83;
            else
                return;
            if ((Status & 7) != 1) return;
            if (!(Status & Cause & 0xFF00)) return;
            break;

        case HW2_INT:
            // Hardware Interrupt 2 -- remove interrupt event from queue
            remove_interupt_event();
            // setup r4300 Status flags: reset TS, and SR, set IM2
            Status = (Status & ~0x00380000) | 0x1000;
            Cause = (Cause | 0x1000) & 0xFFFFFF83;
            /* the exception_general() call below will jump to the interrupt vector (0x80000180) and setup the
             * interpreter or dynarec
             */
            break;

        case NMI_INT:
            // Non Maskable Interrupt -- remove interrupt event from queue
            remove_interupt_event();
            // setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR
            Status = (Status & ~0x00380000) | 0x00500004;
            Cause  = 0x00000000;
            // simulate the soft reset code which would run from the PIF ROM
            r4300_reset_soft();
            // clear all interrupts, reset interrupt counters back to 0
            Count = 0;
            vi_counter = 0;
            init_interupt();
            // clear the audio status register so that subsequent write_ai() calls will work properly
            ai_register.ai_status = 0;
            // set ErrorEPC with the last instruction address
            ErrorEPC = PC->addr;
            // reset the r4300 internal state
            if (r4300emu != CORE_PURE_INTERPRETER)
            {
                // clear all the compiled instruction blocks and re-initialize
                free_blocks();
                init_blocks();
            }
            // adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags
            if(delay_slot==1 || delay_slot==3)
            {
                ErrorEPC-=4;
            }
            delay_slot = 0;
            dyna_interp = 0;
            // set next instruction address to reset vector
            last_addr = 0xa4000040;
            generic_jump_to(0xa4000040);
            return;

        default:
            DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q->type);
            remove_interupt_event();
            break;
    }

#ifdef NEW_DYNAREC
    if (r4300emu == CORE_DYNAREC) {
        EPC = pcaddr;
        pcaddr = 0x80000180;
        Status |= 2;
        Cause &= 0x7FFFFFFF;
        pending_exception=1;
    } else {
        exception_general();
    }
#else
    exception_general();
#endif
}