diff options
| author | Merry <MerryMage@users.noreply.github.com> | 2018-07-12 19:51:02 +0100 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-07-12 15:51:02 -0300 |
| commit | b233ae964fcaae900cdefa6ce51b0edb2892dfaf (patch) | |
| tree | 53968c715100251ac6ced620ea2b6fe04c1a6d1e /ChocolArm64/Instruction/ASoftFloat.cs | |
| parent | cd18ab29dfacd1f7a3218d4ec73ce664bccc3887 (diff) | |
AInstEmitSimdCvt: Half-precision to single-precision conversion (#235)
Diffstat (limited to 'ChocolArm64/Instruction/ASoftFloat.cs')
| -rw-r--r-- | ChocolArm64/Instruction/ASoftFloat.cs | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/ChocolArm64/Instruction/ASoftFloat.cs b/ChocolArm64/Instruction/ASoftFloat.cs index e63c82be..27f4f7fb 100644 --- a/ChocolArm64/Instruction/ASoftFloat.cs +++ b/ChocolArm64/Instruction/ASoftFloat.cs @@ -225,5 +225,41 @@ namespace ChocolArm64.Instruction return 2.0 + op1 * op2; } + + public static float ConvertHalfToSingle(ushort x) + { + uint x_sign = (uint)(x >> 15) & 0x0001; + uint x_exp = (uint)(x >> 10) & 0x001F; + uint x_mantissa = (uint)x & 0x03FF; + + if (x_exp == 0 && x_mantissa == 0) + { + // Zero + return BitConverter.Int32BitsToSingle((int)(x_sign << 31)); + } + + if (x_exp == 0x1F) + { + // NaN or Infinity + return BitConverter.Int32BitsToSingle((int)((x_sign << 31) | 0x7F800000 | (x_mantissa << 13))); + } + + int exponent = (int)x_exp - 15; + + if (x_exp == 0) + { + // Denormal + x_mantissa <<= 1; + while ((x_mantissa & 0x0400) == 0) + { + x_mantissa <<= 1; + exponent--; + } + x_mantissa &= 0x03FF; + } + + uint new_exp = (uint)((exponent + 127) & 0xFF) << 23; + return BitConverter.Int32BitsToSingle((int)((x_sign << 31) | new_exp | (x_mantissa << 13))); + } } }
\ No newline at end of file |
