private void Inst_Dmtc1(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst.Fs)) { CauseFPUException(FPUExceptionType.Unimplemented); return; } UInt64 value = MipsState.ReadGPRUnsigned(inst.Rt); if (MipsState.CP0Regs.StatusReg.AdditionalFPR) { MipsState.Fpr.WriteFPRUnsigned(inst.Fs, value); } else { MipsState.Fpr.WriteFPR32Unsigned(inst.Fs + 1, (UInt32)(value >> 32)); MipsState.Fpr.WriteFPR32Unsigned(inst.Fs, (UInt32)(value & 0xFFFFFFFF)); } }
private void Inst_Addi(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { try { MipsState.WriteGPR32Signed(inst.Rt, MipsState.ReadGPR32Signed(inst.Rs) + (Int32)(Int16)inst.Immediate); } catch (OverflowException) { CauseException = ExceptionCode.OverFlow; } } else { try { MipsState.WriteGPRSigned(inst.Rt, MipsState.ReadGPRSigned(inst.Rs) + (Int64)(Int16)inst.Immediate); } catch (OverflowException) { CauseException = ExceptionCode.OverFlow; } } }
private void Inst_Sltu(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { if (MipsState.ReadGPR32Unsigned(inst.Rs) < MipsState.ReadGPR32Unsigned(inst.Rt)) { MipsState.GPRRegs[inst.Rd] = 1; } else { MipsState.GPRRegs[inst.Rd] = 0; } } else { if (MipsState.ReadGPRUnsigned(inst.Rs) < MipsState.ReadGPRUnsigned(inst.Rt)) { MipsState.GPRRegs[inst.Rd] = 1; } else { MipsState.GPRRegs[inst.Rd] = 0; } } }
private void Inst_Subu(MipsInstruction inst) { unchecked { MipsState.WriteGPR32Unsigned(inst.Rd, MipsState.ReadGPR32Unsigned(inst.Rs) - MipsState.ReadGPR32Unsigned(inst.Rt)); } }
private void Inst_Dmfc1(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst.Fs)) { CauseFPUException(FPUExceptionType.Unimplemented); return; } UInt64 value = 0; if (MipsState.CP0Regs.StatusReg.AdditionalFPR) { value = MipsState.Fpr.ReadFPRUnsigned(inst.Fs); } else { value = MipsState.Fpr.ReadFPR32Unsigned(inst.Fs + 1) << 32; value |= MipsState.Fpr.ReadFPR32Unsigned(inst.Fs); } MipsState.WriteGPRUnsigned(inst.Rt, value); }
private void Inst_Lhu(MipsInstruction inst) { try { Int64 address = ComputeAddress(inst); if ((address & 1) != 0) { CauseException = ExceptionCode.AddressErrorLoad; return; } if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rt, DataManipulator.LoadHalfwordUnsigned(address)); } else { MipsState.WriteGPRUnsigned(inst.Rt, DataManipulator.LoadHalfwordUnsigned(address)); } } catch (TLBException tlbe) { switch (tlbe.ExceptionType) { case TLBExceptionType.Invalid: CauseException = ExceptionCode.Invalid; break; case TLBExceptionType.Mod: CauseException = ExceptionCode.TlbMod; break; case TLBExceptionType.Refill: CauseException = ExceptionCode.TlbStore; break; default: break; } } }
private void Inst_Lbu(MipsInstruction inst) { try { if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Signed(inst.Rt, DataManipulator.LoadByteUnsigned(ComputeAddress(inst))); } else { MipsState.WriteGPRSigned(inst.Rt, DataManipulator.LoadByteUnsigned(ComputeAddress(inst))); } } catch (TLBException tlbe) { switch (tlbe.ExceptionType) { case TLBExceptionType.Invalid: CauseException = ExceptionCode.Invalid; break; case TLBExceptionType.Mod: CauseException = ExceptionCode.TlbMod; break; case TLBExceptionType.Refill: CauseException = ExceptionCode.TlbStore; break; default: break; } } }
private void Inst_Add(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { try { MipsState.WriteGPR32Signed(inst.Rd, MipsState.ReadGPR32Signed(inst.Rs) + MipsState.ReadGPR32Signed(inst.Rt)); } catch (OverflowException) { CauseException = ExceptionCode.OverFlow; } } else { if (MipsState.ReadGPRUnsigned(inst.Rs).IsSigned32() && MipsState.ReadGPRUnsigned(inst.Rt).IsSigned32()) { try { MipsState.WriteGPRSigned(inst.Rd, MipsState.ReadGPRSigned(inst.Rs) + MipsState.ReadGPRSigned(inst.Rt)); } catch (OverflowException) { CauseException = ExceptionCode.OverFlow; } } } }
private void Inst_Mtc0(MipsInstruction inst) { if (MipsState.CP0Regs.StatusReg.CopUsable0) { var regType = (CP0RegName)inst.Rd; switch (regType) { default: MipsState.CP0Regs[inst.Rd] = MipsState.ReadGPRUnsigned(inst.Rt); break; case CP0RegName.Count: { UInt32 count = (UInt32)MipsState.CP0Regs[inst.Rd]; UInt32 newCount = (UInt32)MipsState.ReadGPRUnsigned(inst.Rt); MipsState.CP0Regs.Count = newCount; MupenHelper.UpdateCount(); if (MupenHelper.NextInterrupt <= count) { MupenHelper.GenInterrupt(); } MupenHelper.TranslateEventQueue(newCount); break; } case CP0RegName.Compare: { UInt32 newCompare = (UInt32)MipsState.ReadGPRUnsigned(inst.Rt); MipsState.CP0Regs.Compare = newCompare; MupenHelper.UpdateCount(); MupenHelper.RemoveEvent(MupenHelper.COMPARE_INT); MupenHelper.AddInterruptEventCount(MupenHelper.COMPARE_INT, newCompare); MipsState.CP0Regs.Cause &= 0xFFFF7FFFU; break; } case CP0RegName.SR: { UInt32 newStatus = (UInt32)MipsState.ReadGPRUnsigned(inst.Rt); MipsState.CP0Regs.Status = newStatus; MupenHelper.UpdateCount(); MupenHelper.CheckInterrupt(); if (MupenHelper.NextInterrupt <= MipsState.CP0Regs.Count) { MupenHelper.GenInterrupt(); } break; } } } else { CauseException = ExceptionCode.CopUnstable; } }
private void Inst_Swr(MipsInstruction inst) { /* Thanks to PJ64 */ Int64 address = ComputeAddress(inst); Int32 offset = (Int32)(address & 3); UInt32 value = DataManipulator.LoadWordUnsigned(address & ~3); value &= SWRMask[offset]; value += MipsState.ReadGPR32Unsigned(inst.Rt) << SWRShift[offset]; DataManipulator.Store(address & ~3, value); }
private void Inst_Dmfc0(MipsInstruction inst) { if (MipsState.Operating64BitMode) { MipsState.WriteGPRUnsigned(inst.Rt, MipsState.CP0Regs[inst.Rd]); } else { CauseException = ExceptionCode.ReservedInstruction; } }
private void Inst_Bnel(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { DoBranchLikely(MipsState.ReadGPR32Unsigned(inst.Rs) != MipsState.ReadGPR32Unsigned(inst.Rt), inst); } else { DoBranchLikely(MipsState.ReadGPRUnsigned(inst.Rs) != MipsState.ReadGPRUnsigned(inst.Rt), inst); } }
private void Inst_Xori(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Signed(inst.Rt, MipsState.ReadGPR32Signed(inst.Rs) ^ (Int32)(Int16)inst.Immediate); } else { MipsState.WriteGPRSigned(inst.Rt, MipsState.ReadGPRSigned(inst.Rs) ^ (Int64)(Int16)inst.Immediate); } }
private void Inst_Bgez(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { DoBranch(MipsState.ReadGPR32Signed(inst.Rs) >= 0, inst); } else { DoBranch(MipsState.ReadGPRSigned(inst.Rs) >= 0, inst); } }
private void Inst_Dsrl32(MipsInstruction inst) { if (MipsState.Operating64BitMode) { MipsState.WriteGPRUnsigned(inst.Rd, MipsState.ReadGPRUnsigned(inst.Rt) >> (32 + inst.ShiftAmount)); } else { CauseException = ExceptionCode.ReservedInstruction; } }
private void Inst_Xor(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rd, MipsState.ReadGPR32Unsigned(inst.Rs) ^ MipsState.ReadGPR32Unsigned(inst.Rt)); } else { MipsState.WriteGPRUnsigned(inst.Rd, MipsState.ReadGPRUnsigned(inst.Rs) ^ MipsState.ReadGPRUnsigned(inst.Rt)); } }
private void Inst_Sub(MipsInstruction inst) { try { MipsState.WriteGPR32Signed(inst.Rd, MipsState.ReadGPR32Signed(inst.Rs) - MipsState.ReadGPR32Signed(inst.Rt)); } catch (OverflowException) { CauseException = ExceptionCode.OverFlow; } }
private void Inst_Andi(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rt, MipsState.ReadGPR32Unsigned(inst.Rs) & (UInt32)inst.Immediate); } else { MipsState.WriteGPRUnsigned(inst.Rt, MipsState.ReadGPRUnsigned(inst.Rs) & (UInt64)inst.Immediate); } }
private void Inst_Dsrlv(MipsInstruction inst) { if (MipsState.Operating64BitMode) { MipsState.WriteGPRUnsigned(inst.Rd, MipsState.ReadGPRUnsigned(inst.Rt) >> (Int32)(MipsState.ReadGPR32Unsigned(inst.Rs) & 0x3FUL)); } else { CauseException = ExceptionCode.ReservedInstruction; } }
private void Inst_Bltzl(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { DoBranchLikely(MipsState.ReadGPR32Signed(inst.Rs) < 0, inst); } else { DoBranchLikely(MipsState.ReadGPRSigned(inst.Rs) < 0, inst); } }
private void Inst_Sh(MipsInstruction inst) { Int64 address = ComputeAddress(inst); if ((address & 1) != 0) { CauseException = ExceptionCode.AddressErrorStore; return; } DataManipulator.Store(address, (UInt16)MipsState.ReadGPRUnsigned(inst.Rt)); }
private void Inst_Lui(MipsInstruction inst) { UInt32 word = ((UInt32)inst.Immediate) << 16; if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rt, word); } else { MipsState.WriteGPRUnsigned(inst.Rt, (UInt64)(Int64)(Int32)word); } }
private void Inst_Srvl(MipsInstruction inst) { UInt32 result = MipsState.ReadGPR32Unsigned(inst.Rt) >> MipsState.ReadGPR32Signed(inst.Rs) & 0x1F; if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rd, result); } else { MipsState.WriteGPRUnsigned(inst.Rd, (UInt32)(Int32)result); } }
private void Inst_Srav(MipsInstruction inst) { Int32 result = MipsState.ReadGPR32Signed(inst.Rt) >> (MipsState.ReadGPR32Signed(inst.Rs) & 0x1F); if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Signed(inst.Rd, result); } else { MipsState.WriteGPRSigned(inst.Rd, result); } }
private void Inst_Sra(MipsInstruction inst) { Int32 result = MipsState.ReadGPR32Signed(inst.Rt) >> inst.ShiftAmount; if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Signed(inst.Rd, result); } else { MipsState.WriteGPRSigned(inst.Rd, result); } }
private void Inst_Srl(MipsInstruction inst) { UInt32 result = MipsState.ReadGPR32Unsigned(inst.Rt) >> inst.ShiftAmount; if (!MipsState.Operating64BitMode) { MipsState.WriteGPR32Unsigned(inst.Rd, result); } else { MipsState.WriteGPRUnsigned(inst.Rd, (UInt64)(Int64)(Int16)result); } }
private void Inst_Sltiu(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { Boolean condition = MipsState.ReadGPR32Unsigned(inst.Rs) < ((UInt32)(Int32)(Int16)inst.Immediate); MipsState.WriteGPR32Unsigned(inst.Rt, condition ? 1U : 0U); } else { Boolean condition = MipsState.ReadGPRUnsigned(inst.Rs) < ((UInt64)(Int64)(Int16)inst.Immediate); MipsState.WriteGPRUnsigned(inst.Rt, condition ? 1UL : 0UL); } }
private void Inst_Sw(MipsInstruction inst) { Int64 address = ComputeAddress(inst); if ((address & 3) != 0) { CauseException = ExceptionCode.AddressErrorStore; } else { DataManipulator.Store(address, MipsState.ReadGPR32Unsigned(inst.Rt)); } }
private void Inst_Daddiu(MipsInstruction inst) { if (!MipsState.Operating64BitMode) { CauseException = ExceptionCode.ReservedInstruction; } else { unchecked { MipsState.WriteGPRUnsigned(inst.Rd, MipsState.ReadGPRUnsigned(inst.Rs) + (UInt64)(Int64)(Int16)inst.Immediate); } } }
private void Inst_Dsubu(MipsInstruction inst) { if (MipsState.Operating64BitMode) { unchecked { MipsState.WriteGPRUnsigned(inst.Rd, MipsState.ReadGPRUnsigned(inst.Rs) - MipsState.ReadGPRUnsigned(inst.Rt)); } } else { CauseException = ExceptionCode.ReservedInstruction; } }