📄 float.c
字号:
BOOLEAN fCop1XInstruction;
FP_SINGLE_OPERAND SingleOperand4;
FP_DOUBLE_OPERAND DoubleOperand4;
#endif
ULONG Function;
ULONG Index;
MIPS_INSTRUCTION Instruction;
ULARGE_INTEGER LargeResult;
LONG Longword;
LONG Negation;
union {
LONGLONG Quadword;
LARGE_INTEGER LargeValue;
}u;
LONG SingleMantissa;
FP_SINGLE_OPERAND SingleOperand1;
FP_SINGLE_OPERAND SingleOperand2;
FP_SINGLE_OPERAND SingleOperand3;
ULONG SingleValue;
ULONG StickyBits;
//
// Save the original exception address in case another exception
// occurs.
//
ExceptionAddress = ExceptionRecord->ExceptionAddress;
//
// Any exception that occurs during the attempted emulation of the
// floating operation causes the emulation to be aborted. The new
// exception code and information is copied to the original exception
// record and a value of FALSE is returned.
//
try {
//
// If the exception PC is equal to the fault instruction address
// plus four, then the floating exception occurred in the delay
// slot of a branch instruction and the continuation address must
// be computed by emulating the branch instruction. Note that it
// is possible for an exception to occur when the branch instruction
// is read from user memory.
//
if (cause.BD)
ContextBlock.BranchAddress = KiEmulateBranch(pctx);
else
ContextBlock.BranchAddress = pctx->Fir + 4;
//
// Initialize the address of the exception record, exception frame,
// and trap frame in the context block used during the emulation of
// the floating point operation.
//
ContextBlock.ExceptionRecord = ExceptionRecord;
ContextBlock.pctx = pctx;
ContextBlock.Round = ((PFSR)&pctx->Fsr)->RM;
//
// Initialize the number of exception information parameters, set
// the branch address, and clear the IEEE exception value.
//
ExceptionRecord->NumberParameters = 6;
ExceptionRecord->ExceptionInformation[0] = 0;
ExceptionRecord->ExceptionInformation[1] = ContextBlock.BranchAddress;
ExceptionRecord->ExceptionInformation[2] = 0;
ExceptionRecord->ExceptionInformation[3] = 0;
ExceptionRecord->ExceptionInformation[4] = 0;
ExceptionRecord->ExceptionInformation[5] = 0;
//
// Clear all exception flags and emulate the floating point operation
// The return value is dependent on the results of the emulation.
//
pctx->Fsr &= ~(0x3f << 12);
Instruction = *((PMIPS_INSTRUCTION)ExceptionAddress + (cause.BD ? 1 : 0));
#ifdef _MIPS64
if (Instruction.c_format.Opcode == COP1X_OP) {
fCop1XInstruction = TRUE;
Function = Instruction.cx_format.Function;
ContextBlock.Fd = Instruction.cx_format.Fd;
Fs = Instruction.cx_format.Fs;
Ft = Instruction.cx_format.Ft;
Fr = Instruction.cx_format.Fr;
Format = Instruction.cx_format.Format;
} else {
fCop1XInstruction = FALSE;
Function = Instruction.c_format.Function;
ContextBlock.Fd = Instruction.c_format.Fd;
Fs = Instruction.c_format.Fs;
Ft = Instruction.c_format.Ft;
Format = Instruction.c_format.Format;
}
#else
Function = Instruction.c_format.Function;
ContextBlock.Fd = Instruction.c_format.Fd;
Fs = Instruction.c_format.Fs;
Ft = Instruction.c_format.Ft;
Format = Instruction.c_format.Format;
#endif
Negation = 0;
//
// Check for illegal register specification or format code.
// NOTE: only MIPS64 use odd-number floating registers (fr1, fr3, fr5, ...)
//
if (
#ifndef _MIPS64
((ContextBlock.Fd & 0x1) != 0) || ((Fs & 0x1) != 0) || ((Ft & 0x1) != 0) ||
#endif
((Format != FORMAT_LONGWORD) && (Format != FORMAT_QUADWORD) && (Format > FORMAT_DOUBLE))) {
Function = FLOAT_ILLEGAL;
}
//
// Decode operand values and dispose with NaNs.
//
#ifdef _MIPS64
if (fCop1XInstruction) {
if (Function >= FLOAT_MADD && Function <= FLOAT_NMSUB) {
//
// The function has three operand values
//
if (Format == FORMAT_SINGLE) {
KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1);
KiUnpackSingle(Ft, &ContextBlock, &SingleOperand2);
KiUnpackSingle(Fr, &ContextBlock, &SingleOperand4);
//
// If one of operand is a NaN, then it is a Dyadic operation
//
if (SingleOperand1.Nan != FALSE || SingleOperand2.Nan != FALSE || SingleOperand4.Nan != FALSE) {
//
// Dyadic operation.
//
// Store a quite Nan if the invalid operation trap
// is disabled, or raise an exception if the invalid
// operation trap is enabled and either of the NaNs
// is a signally NaN.
//
return KiInvalidOperationSingle(&ContextBlock,
TRUE,
&SingleOperand1,
(SingleOperand2.Nan != FALSE) ? &SingleOperand2 : &SingleOperand4);
}
} else if (Format == FORMAT_DOUBLE) {
KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1);
KiUnpackDouble(Ft, &ContextBlock, &DoubleOperand2);
KiUnpackDouble(Fr, &ContextBlock, &DoubleOperand4);
//
// If one of operand is a NaN, then it is a Dyadic operation
//
if (DoubleOperand1.Nan != FALSE || DoubleOperand2.Nan != FALSE || DoubleOperand4.Nan != FALSE) {
//
// Dyadic operation.
//
// Store a quite Nan if the invalid operation trap
// is disabled, or raise an exception if the invalid
// operation trap is enabled and either of the NaNs
// is a signally NaN.
//
return KiInvalidOperationDouble(&ContextBlock,
TRUE,
&DoubleOperand1,
(DoubleOperand2.Nan != FALSE) ? &DoubleOperand2 : &DoubleOperand4);
}
} else {
//
// invalid format
//
Function = FLOAT_ILLEGAL;
}
} else {
//
// invalid instruction
//
Function = FLOAT_ILLEGAL;
}
} else
#endif
if ((Function <= FLOAT_DIVIDE) || (Function >= FLOAT_COMPARE)) {
//
// The function has two operand values.
//
if (Format == FORMAT_SINGLE) {
KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1);
KiUnpackSingle(Ft, &ContextBlock, &SingleOperand2);
//
// If either operand is a NaN, then check to determine if a
// compare instruction or other dyadic operation is being
// performed.
//
if ((SingleOperand1.Nan != FALSE) || (SingleOperand2.Nan != FALSE)) {
if (Function < FLOAT_COMPARE) {
//
// Dyadic operation.
//
// Store a quite Nan if the invalid operation trap
// is disabled, or raise an exception if the invalid
// operation trap is enabled and either of the NaNs
// is a signally NaN.
//
return KiInvalidOperationSingle(&ContextBlock,
TRUE,
&SingleOperand1,
&SingleOperand2);
} else {
//
// Compare operation.
//
// Set the condition based on the predicate of
// the floating comparison.
//
// If the compare is a signaling compare, then
// raise an exception if the invalid operation
// trap is enabled. Otherwise, raise an exception
// if one of the operands is a signaling NaN.
//
if ((Function & COMPARE_UNORDERED_MASK) != 0) {
((PFSR)&pctx->Fsr)->CC = 1;
} else {
((PFSR)&pctx->Fsr)->CC = 0;
}
if ((Function & COMPARE_ORDERED_MASK) != 0) {
return KiInvalidCompareSingle(&ContextBlock,
FALSE,
&SingleOperand1,
&SingleOperand2);
} else {
return KiInvalidCompareSingle(&ContextBlock,
TRUE,
&SingleOperand1,
&SingleOperand2);
}
}
} else if (Function >= FLOAT_COMPARE) {
CompareFunction = Function;
Function = FLOAT_COMPARE_SINGLE;
}
} else if (Format == FORMAT_DOUBLE) {
KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1);
KiUnpackDouble(Ft, &ContextBlock, &DoubleOperand2);
//
// If either operand is a NaN, then check to determine if a
// compare instruction or other dyadic operation is being
// performed.
//
if ((DoubleOperand1.Nan != FALSE) || (DoubleOperand2.Nan != FALSE)) {
if (Function < FLOAT_COMPARE) {
//
// Dyadic operation.
//
// Store a quite Nan if the invalid operation trap
// is disabled, or raise an exception if the invalid
// operation trap is enabled and either of the NaNs
// is a signally NaN.
//
return KiInvalidOperationDouble(&ContextBlock,
TRUE,
&DoubleOperand1,
&DoubleOperand2);
} else {
//
// Compare operation.
//
// Set the condition based on the predicate of
// the floating comparison.
//
// If the compare is a signaling compare, then
// raise an exception if the invalid operation
// trap is enabled. Othersie, raise an exception
// if one of the operands is a signaling NaN.
//
if ((Function & COMPARE_UNORDERED_MASK) != 0) {
((PFSR)&pctx->Fsr)->CC = 1;
} else {
((PFSR)&pctx->Fsr)->CC = 0;
}
if ((Function & COMPARE_ORDERED_MASK) != 0) {
return KiInvalidCompareDouble(&ContextBlock,
FALSE,
&DoubleOperand1,
&DoubleOperand2);
} else {
return KiInvalidCompareDouble(&ContextBlock,
TRUE,
&DoubleOperand1,
&DoubleOperand2);
}
}
} else if (Function >= FLOAT_COMPARE) {
CompareFunction = Function;
Function = FLOAT_COMPARE_DOUBLE;
}
} else {
Function = FLOAT_ILLEGAL;
}
} else {
//
// The function has one operand value.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -