📄 float.c
字号:
if (Format == FORMAT_SINGLE) {
KiUnpackSingle(Fs, &ContextBlock, &SingleOperand1);
//
// If the operand is a NaN and the function is not a convert
// operation, then store a quiet NaN if the invalid operation
// trap is disabled, or raise an exception if the invalid
// operation trap is enabled and the operand is a signaling
// NaN.
//
if ((SingleOperand1.Nan != FALSE) &&
(Function < FLOAT_ROUND_QUADWORD) ||
(Function > FLOAT_CONVERT_QUADWORD) ||
((Function > FLOAT_FLOOR_LONGWORD) &&
(Function < FLOAT_CONVERT_SINGLE))) {
return KiInvalidOperationSingle(&ContextBlock,
TRUE,
&SingleOperand1,
&SingleOperand1);
}
} else if (Format == FORMAT_DOUBLE) {
KiUnpackDouble(Fs, &ContextBlock, &DoubleOperand1);
//
// If the operand is a NaN and the function is not a convert
// operation, then store a quiet NaN if the invalid operation
// trap is disabled, or raise an exception if the invalid
// operation trap is enabled and the operand is a signaling
// NaN.
//
if ((DoubleOperand1.Nan != FALSE) &&
(Function < FLOAT_ROUND_QUADWORD) ||
(Function > FLOAT_CONVERT_QUADWORD) ||
((Function > FLOAT_FLOOR_LONGWORD) &&
(Function < FLOAT_CONVERT_SINGLE))) {
return KiInvalidOperationDouble(&ContextBlock,
TRUE,
&DoubleOperand1,
&DoubleOperand1);
}
} else if ((Format == FORMAT_LONGWORD) &&
(Function >= FLOAT_CONVERT_SINGLE)) {
Longword = KiGetRegisterValue(Fs + 32,
ContextBlock.pctx);
} else if ((Format == FORMAT_QUADWORD) &&
(Function >= FLOAT_CONVERT_SINGLE)) {
u.Quadword = KiGetRegisterDouble(Fs + 32,
ContextBlock.pctx);
} else {
Function = FLOAT_ILLEGAL;
}
}
//
// Case to the proper function routine to emulate the operation.
//
#ifdef _MIPS64
if (fCop1XInstruction && Function != FLOAT_ILLEGAL) {
if (Format == FORMAT_SINGLE) {
//
// Reorder the operands according to their exponent value.
//
if (SingleOperand2.Exponent > SingleOperand1.Exponent) {
SingleOperand3 = SingleOperand2;
SingleOperand2 = SingleOperand1;
SingleOperand1 = SingleOperand3;
}
//
// If the first operand is infinite and the second operand is
// zero, then an invalid operation is specified.
//
if ((SingleOperand1.Infinity != FALSE) &&
(SingleOperand2.Infinity == FALSE) &&
(SingleOperand2.Mantissa == 0)) {
return KiInvalidOperationSingle(&ContextBlock,
FALSE,
&SingleOperand1,
&SingleOperand2);
}
//
// Preshift the operand mantissas so the result will be a
// properly aligned 64-bit value and then unsigned multiply
// the two mantissa values. The single result is the high part
// of the 64-bit product and the sticky bits are the low part
// of the 64-bit product.
//
LargeResult.QuadPart = UInt32x32To64(SingleOperand1.Mantissa << (32 - 26),
SingleOperand2.Mantissa << 1);
SingleOperand1.Mantissa = LargeResult.HighPart;
StickyBits = LargeResult.LowPart;
//
// Compute the sign and exponent of the result.
//
SingleOperand1.Sign ^= SingleOperand2.Sign;
SingleOperand1.Exponent +=
SingleOperand2.Exponent - SINGLE_EXPONENT_BIAS;
//
// perform ADD/SUB
//
SingleOperand2 = SingleOperand4;
if (Function == FLOAT_MSUB || Function == FLOAT_NMSUB)
Negation = 0x1;
//
// Complement the sign of the second operand if the operation
// is subtraction.
//
SingleOperand2.Sign ^= Negation;
//
// Reorder then operands according to their exponent value.
//
if (SingleOperand2.Exponent > SingleOperand1.Exponent) {
SingleOperand3 = SingleOperand2;
SingleOperand2 = SingleOperand1;
SingleOperand1 = SingleOperand3;
}
//
// Compute the exponent difference and shift the smaller
// mantissa right by the difference value or 26 which ever
// is smaller. The bits shifted out are termed the sticky
// bits and are used later in the rounding operation.
//
ExponentDifference =
SingleOperand1.Exponent - SingleOperand2.Exponent;
if (ExponentDifference > 26) {
ExponentDifference = 26;
}
StickyBits =
SingleOperand2.Mantissa & ((1 << ExponentDifference) - 1);
SingleMantissa = SingleOperand2.Mantissa >> ExponentDifference;
//
// If the operands both have the same sign, then perform the
// operation by adding the values together. Otherwise, perform
// the operation by subtracting the second operand from the
// first operand.
//
if ((SingleOperand1.Sign ^ SingleOperand2.Sign) == 0) {
SingleOperand1.Mantissa += SingleMantissa;
} else {
if ((SingleOperand1.Infinity != FALSE) &&
(SingleOperand2.Infinity != FALSE)) {
return KiInvalidOperationSingle(&ContextBlock,
FALSE,
&SingleOperand1,
&SingleOperand2);
} else if (SingleOperand1.Infinity == FALSE) {
if (StickyBits != 0) {
SingleOperand1.Mantissa -= 1;
}
SingleOperand1.Mantissa -= SingleMantissa;
if (SingleOperand1.Mantissa < 0) {
SingleOperand1.Mantissa = -SingleOperand1.Mantissa;
SingleOperand1.Sign ^= 0x1;
}
}
}
if (Function == FLOAT_NMADD || Function == FLOAT_NMSUB)
SingleOperand1.Sign ^= 0x1;
//
// Normalize and store the result value.
//
return KiNormalizeSingle(&ContextBlock,
&SingleOperand1,
StickyBits);
} else if (Format == FORMAT_DOUBLE) {
//
// Reorder the operands according to their exponent value.
//
if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) {
DoubleOperand3 = DoubleOperand2;
DoubleOperand2 = DoubleOperand1;
DoubleOperand1 = DoubleOperand3;
}
//
// If the first operand is infinite and the second operand is
// zero, then an invalid operation is specified.
//
if ((DoubleOperand1.Infinity != FALSE) &&
(DoubleOperand2.Infinity == FALSE) &&
(DoubleOperand2.MantissaHigh == 0)) {
return KiInvalidOperationDouble(&ContextBlock,
FALSE,
&DoubleOperand1,
&DoubleOperand2);
}
//
// Preshift the operand mantissas so the result will be a
// properly aligned 128-bit value and then unsigned multiply
// the two mantissa values. The double result is the high part
// of the 128-bit product and the sticky bits are the low part
// of the 128-bit product.
//
DoubleOperand1.MantissaHigh =
(DoubleOperand1.MantissaHigh << 1) |
(DoubleOperand1.MantissaLow >> 31);
DoubleOperand1.MantissaLow <<= 1;
DoubleOperand2.MantissaHigh =
(DoubleOperand2.MantissaHigh << (64 - 55)) |
(DoubleOperand2.MantissaLow >> (32 - (64 -55)));
DoubleOperand2.MantissaLow <<= (64 - 55);
//
// The 128-bit product is formed by mutiplying and adding
// all the cross product values.
//
// Consider the operands (A and B) as being composed of two
// parts Ahigh, Alow, Bhigh, and Blow. The cross product sum
// is then:
//
// Ahigh * Bhigh * 2^64 +
// Ahigh * Blow * 2^32 +
// Alow * Bhigh * 2^32 +
// Alow * Blow
//
AhighBhigh.QuadPart = UInt32x32To64(DoubleOperand1.MantissaHigh,
DoubleOperand2.MantissaHigh);
AhighBlow.QuadPart = UInt32x32To64(DoubleOperand1.MantissaHigh,
DoubleOperand2.MantissaLow);
AlowBhigh.QuadPart = UInt32x32To64(DoubleOperand1.MantissaLow,
DoubleOperand2.MantissaHigh);
AlowBlow.QuadPart = UInt32x32To64(DoubleOperand1.MantissaLow,
DoubleOperand2.MantissaLow);
AlowBlow.HighPart += AhighBlow.LowPart;
if (AlowBlow.HighPart < AhighBlow.LowPart) {
Carry1 = 1;
} else {
Carry1 = 0;
}
AlowBlow.HighPart += AlowBhigh.LowPart;
if (AlowBlow.HighPart < AlowBhigh.LowPart) {
Carry1 += 1;
}
DoubleOperand1.MantissaLow = AhighBlow.HighPart + Carry1;
if (DoubleOperand1.MantissaLow < Carry1) {
Carry2 = 1;
} else {
Carry2 = 0;
}
DoubleOperand1.MantissaLow += AlowBhigh.HighPart;
if (DoubleOperand1.MantissaLow < AlowBhigh.HighPart) {
Carry2 += 1;
}
DoubleOperand1.MantissaLow += AhighBhigh.LowPart;
if (DoubleOperand1.MantissaLow < AhighBhigh.LowPart) {
Carry2 += 1;
}
DoubleOperand1.MantissaHigh = AhighBhigh.HighPart + Carry2;
StickyBits = AlowBlow.HighPart | AlowBlow.LowPart;
//
// Compute the sign and exponent of the result.
//
DoubleOperand1.Sign ^= DoubleOperand2.Sign;
DoubleOperand1.Exponent +=
DoubleOperand2.Exponent - DOUBLE_EXPONENT_BIAS;
//
// perform ADD/SUB
//
DoubleOperand2 = DoubleOperand4;
if (Function == FLOAT_MSUB || Function == FLOAT_NMSUB)
Negation = 0x1;
//
// Complement the sign of the second operand if the operation
// is subtraction.
//
DoubleOperand2.Sign ^= Negation;
//
// Reorder then operands according to their exponent value.
//
if (DoubleOperand2.Exponent > DoubleOperand1.Exponent) {
DoubleOperand3 = DoubleOperand2;
DoubleOperand2 = DoubleOperand1;
DoubleOperand1 = DoubleOperand3;
}
//
// Compute the exponent difference and shift the smaller
// mantissa right by the difference value or 55 which ever
// is smaller. The bits shifted out are termed the sticky
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -