private void Inst_FpuMov(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUEntity value = new FPUEntity(format, MipsState); value.Load(inst.Fs); value.Store(inst.Fd); } else { CauseFPUException(FPUExceptionType.Unimplemented); } }
private void Inst_FpuCond(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUEntity a = new FPUEntity(format, MipsState); FPUEntity b = new FPUEntity(format, MipsState); Boolean less = false; Boolean unordered = false; Boolean equal = false; Boolean condU = (inst.Function & 1) != 0; Boolean condE = ((inst.Function >> 1) & 1) != 0; Boolean condL = ((inst.Function >> 2) & 1) != 0; a.Load(inst.Fs); b.Load(inst.Ft); if (a.IsNaN && b.IsNaN) { unordered = true; if ((inst.Function & 8) != 0) { CauseFPUException(FPUExceptionType.Invalid); return; } } else { less = a < b; equal = a == b; } MipsState.FCR31.Condition = ((condL && less) || (condE && equal) || (condU && unordered)); } else { CauseFPUException(FPUExceptionType.Unimplemented); } }
private void Inst_FpuAdd(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUHardware.SetRoundingMode(MipsState.FCR31.RM); FPUEntity left = new FPUEntity(format, MipsState); FPUEntity right = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(format, MipsState); left.Load(inst.Fs); right.Load(inst.Ft); try { result.Value = left + right; result.Store(inst.Fd); } catch (OverflowException) { if (FPUHardware.CheckFPUException()) { CauseFPUException(FPUHardware.GetFPUException()); } } } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuRoundW(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUHardware.SetRoundingMode(FPURoundMode.Near); FPUEntity value = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(DataFormat.Word, MipsState); value.Load(inst.Fs); result.Value = (UInt32)Math.Round(value.Value, MidpointRounding.ToEven); result.Store(inst.Fd); if (FPUHardware.CheckFPUException()) { CauseFPUException(FPUHardware.GetFPUException()); } } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuSqrt(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } unchecked { DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUEntity value = new FPUEntity(format, MipsState); value.Load(inst.Fs); FPUHardware.SetRoundingMode(MipsState.FCR31.RM); value.Value = Math.Sqrt(value.Value); value.Store(inst.Fd); if (FPUHardware.CheckFPUException()) { CauseFPUException(FPUHardware.GetFPUException()); } } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuConvertW(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format != DataFormat.Reserved || format != DataFormat.Word) { FPUEntity value = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(DataFormat.Word, MipsState); value.Load(inst.Fs); result.Value = Convert.ToUInt32(value.Value); value.Store(inst.Fd); if (FPUHardware.CheckFPUException()) { CauseFPUException(FPUHardware.GetFPUException()); } } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuTruncW(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUHardware.SetRoundingMode(FPURoundMode.Chop); FPUEntity value = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(DataFormat.Word, MipsState); value.Load(inst.Fs); result.Value = (UInt32)value.Value; result.Store(inst.Fd); if (FPUHardware.CheckFPUException()) CauseFPUException(FPUHardware.GetFPUException()); } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuSub(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) return; unchecked { DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUEntity left = new FPUEntity(format, MipsState); FPUEntity right = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(format, MipsState); left.Load(inst.Fs); right.Load(inst.Ft); FPUHardware.SetRoundingMode(MipsState.FCR31.RM); result.Value = left - right; result.Store(inst.Fd); if (FPUHardware.CheckFPUException()) CauseFPUException(FPUHardware.GetFPUException()); } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuMov(MipsInstruction inst) { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) return; DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUEntity value = new FPUEntity(format, MipsState); value.Load(inst.Fs); value.Store(inst.Fd); } else { CauseFPUException(FPUExceptionType.Unimplemented); } }
private void Inst_FpuConvertW(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) return; DataFormat format = inst.DecodeDataFormat(); if (format != DataFormat.Reserved || format != DataFormat.Word) { FPUEntity value = new FPUEntity(format, MipsState); FPUEntity result = new FPUEntity(DataFormat.Word, MipsState); value.Load(inst.Fs); result.Value = Convert.ToUInt32(value.Value); value.Store(inst.Fd); if (FPUHardware.CheckFPUException()) CauseFPUException(FPUHardware.GetFPUException()); } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }
private void Inst_FpuAbs(MipsInstruction inst) { unchecked { if (!CheckCop1Usable()) { CauseException = ExceptionCode.CopUnstable; return; } if (!CheckEvenOddAllowed(inst)) { return; } DataFormat format = inst.DecodeDataFormat(); if (format == DataFormat.Single || format == DataFormat.Double) { FPUHardware.SetRoundingMode(MipsState.FCR31.RM); FPUEntity fpuEntitiy = new FPUEntity(format, MipsState); fpuEntitiy.Load(inst.Fs); fpuEntitiy.Value = Math.Abs(fpuEntitiy.Value); fpuEntitiy.Store(inst.Fd); if (FPUHardware.CheckFPUException()) CauseFPUException(FPUHardware.GetFPUException()); } else { CauseFPUException(FPUExceptionType.Unimplemented); } } }