mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 11:01:01 +02:00
This follows discussions from #3413. Followup commits add clang-format file, script and blame ignore lists.
66 lines
1.6 KiB
C++
66 lines
1.6 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
namespace FEXCore::FPState {
|
|
enum class X87Tag : uint8_t { Valid = 0b00, Zero = 0b01, Special = 0b10, Empty = 0b11 };
|
|
|
|
static inline X87Tag GetX87Tag(uint64_t (&Reg)[2], bool Valid) {
|
|
if (!Valid) {
|
|
return X87Tag::Empty;
|
|
}
|
|
|
|
const uint64_t Exponent = Reg[1] & 0x7fff;
|
|
if (Exponent == 0x7fff) {
|
|
// (Pseudo) NaN / Inf
|
|
return X87Tag::Special;
|
|
}
|
|
|
|
const bool JBit = Reg[0] & (1ULL << 63);
|
|
if (Exponent == 0) {
|
|
const uint64_t Fraction = Reg[0] & ((1ULL << 63) - 1);
|
|
if (!JBit && !Fraction) {
|
|
return X87Tag::Zero;
|
|
} else {
|
|
// (Pseudo) Subnormal
|
|
return X87Tag::Special;
|
|
}
|
|
}
|
|
|
|
if (JBit) {
|
|
// Normal
|
|
return X87Tag::Valid;
|
|
} else {
|
|
// Invalid
|
|
return X87Tag::Special;
|
|
}
|
|
}
|
|
|
|
static inline uint16_t ConvertFromAbridgedFTW(uint16_t FSW, uint64_t (&MM)[8][2], uint8_t AbridgedFTW) {
|
|
const uint32_t StackTop = (FSW >> 11) & 0b111;
|
|
|
|
uint16_t FTW = 0;
|
|
for (uint32_t i = 0; i < 8; i++) {
|
|
// The AMD manually incorrectly states there is a direct mapping here, only the intel-manual correctly states
|
|
// the stack-relative behaviour
|
|
const uint16_t StackIndex = (i - StackTop) & 0b111;
|
|
const X87Tag Tag = GetX87Tag(MM[StackIndex], AbridgedFTW & (1 << i));
|
|
FTW |= static_cast<uint8_t>(Tag) << (2 * i);
|
|
}
|
|
|
|
return FTW;
|
|
}
|
|
|
|
static inline uint8_t ConvertToAbridgedFTW(uint16_t FTW) {
|
|
uint8_t AbridgedFTW = 0;
|
|
|
|
for (uint32_t i = 0; i < 8; i++) {
|
|
const X87Tag Tag = static_cast<X87Tag>((FTW >> (2 * i)) & 3);
|
|
AbridgedFTW |= ((Tag == X87Tag::Empty) ? 0 : 1) << i;
|
|
}
|
|
|
|
return AbridgedFTW;
|
|
}
|
|
} // namespace FEXCore::FPState
|