38#ifndef __ARCH_ARM_INSTS_VFP_HH__
39#define __ARCH_ARM_INSTS_VFP_HH__
70 flags[StaticInst::IsMicroop] =
true;
73 flags[StaticInst::IsMicroop] =
74 flags[StaticInst::IsFirstMicroop] =
true;
77 flags[StaticInst::IsMicroop] =
78 flags[StaticInst::IsLastMicroop] =
true;
84 flags[StaticInst::IsDelayedCommit] =
true;
115static inline float bitsToFp(uint64_t,
float);
116static inline double bitsToFp(uint64_t,
double);
117static inline uint32_t
fpToBits(
float);
118static inline uint64_t
fpToBits(
double);
120template <
class fpType>
125 if (std::fpclassify(
op) == FP_SUBNORMAL) {
126 uint64_t bitMask = 0x1ULL << (
sizeof(fpType) * 8 - 1);
133template <
class fpType>
139 return flush1 || flush2;
142template <
class fpType>
151template <
class fpType>
159static inline uint32_t
171static inline uint64_t
207template <
class fpType>
211 const bool single = (
sizeof(fpType) ==
sizeof(
float));
212 const uint64_t qnan =
213 single ? 0x7fc00000 : 0x7ff8000000000000ULL;
222template <
class fpType>
225template <
class fpType>
226fpType
fixDest(FPSCR fpscr, fpType
val, fpType op1, fpType op2);
228template <
class fpType>
234uint16_t
vcvtFpSFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
236uint16_t
vcvtFpDFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
240double vcvtFpHFpD(FPSCR &fpscr,
bool defaultNan,
bool ahp, uint16_t
op);
246 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
249static inline uint32_t
255static inline uint32_t
264 feraiseexcept(exceptions);
274 bool roundAwayFix =
false;
277 rmode = fegetround();
300 panic(
"Unsupported roundMode %d\n", roundMode);
303 __asm__ __volatile__(
"" :
"=m" (rmode) :
"m" (rmode));
306 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
309 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
312 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
316 int fpType = std::fpclassify(
val);
317 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
318 if (fpType == FP_NAN) {
322 }
else if (origVal !=
val) {
325 if (origVal -
val > 0.5)
327 else if (
val - origVal > 0.5)
339 if ( (
error > 0.5) ||
355 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
358 bool outOfRange =
false;
359 int64_t result = (int64_t)
val;
364 finalVal = (int16_t)
val;
365 }
else if (
width == 32) {
366 finalVal =(int32_t)
val;
367 }
else if (
width == 64) {
374 int64_t minVal = ~mask(
width-1);
375 if ((
double)
val < minVal) {
380 if ((
double)
val > maxVal) {
385 bool isNeg =
val < 0;
390 outOfRange = ((uint64_t) result >> (
width - 1)) !=
397 outOfRange |=
val < result;
399 finalVal = 1LL << (
width-1);
402 outOfRange |=
val > result;
412 exceptions &= ~FeInexact;
417 if ((
double)
val < 0) {
419 exceptions &= ~FeInexact;
427 exceptions &= ~FeInexact;
463 return (idx % 32) < 8;
470 OpClass __opClass,
bool _wide) :
544 const bool single = (
sizeof(T) ==
sizeof(
float));
556 bool inf1 = (std::fpclassify(
a) == FP_INFINITE);
557 bool inf2 = (std::fpclassify(
b) == FP_INFINITE);
558 bool zero1 = (std::fpclassify(
a) == FP_ZERO);
559 bool zero2 = (std::fpclassify(
b) == FP_ZERO);
560 if ((inf1 && zero2) || (zero1 && inf2)) {
597 if (
sizeof(T) ==
sizeof(
float))
598 result = fmaf(op1, op2, addend);
600 result = fma(op1, op2, addend);
606 uint64_t bitMask = 0x1ULL << ((
sizeof(T) * 8) - 1);
628 const bool single = (
sizeof(T) ==
sizeof(
float));
629 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
636 if (!std::signbit(
a) && std::signbit(
b))
656 const bool single = (
sizeof(T) ==
sizeof(
float));
657 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
664 if (std::signbit(
a) && !std::signbit(
b))
684 int fpClassA = std::fpclassify(
a);
685 int fpClassB = std::fpclassify(
b);
689 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
690 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
694 fpClassAxB = std::fpclassify(aXb);
695 if (fpClassAxB == FP_SUBNORMAL) {
699 return (3.0 - (
a *
b)) / 2.0;
706 int fpClassA = std::fpclassify(
a);
707 int fpClassB = std::fpclassify(
b);
711 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
712 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
716 fpClassAxB = std::fpclassify(aXb);
717 if (fpClassAxB == FP_SUBNORMAL) {
721 return 2.0 - (
a *
b);
728 int fpClassA = std::fpclassify(
a);
729 int fpClassB = std::fpclassify(
b);
733 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
734 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
738 fpClassAxB = std::fpclassify(aXb);
739 if (fpClassAxB == FP_SUBNORMAL) {
743 return (3.0 - (
a *
b)) / 2.0;
749 int fpClassA = std::fpclassify(
a);
750 int fpClassB = std::fpclassify(
b);
754 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
755 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
759 fpClassAxB = std::fpclassify(aXb);
760 if (fpClassAxB == FP_SUBNORMAL) {
764 return 2.0 - (
a *
b);
773 if (
a -
val == 0.5) {
774 if ( (((
int)
a) & 1) == 0 )
val += 1.0;
776 else if (
a -
val == -0.5) {
777 if ( (((
int)
a) & 1) == 0 )
val -= 1.0;
788 PredOp(mnem, _machInst, __opClass)
792 doOp(
float op1,
float op2)
const
794 panic(
"Unimplemented version of doOp called.\n");
800 panic(
"Unimplemented version of doOp called.\n");
804 doOp(
double op1,
double op2)
const
806 panic(
"Unimplemented version of doOp called.\n");
812 panic(
"Unimplemented version of doOp called.\n");
816 dbl(uint32_t low, uint32_t high)
const
819 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
834 template <
class fpType>
836 processNans(FPSCR &fpscr,
bool &done,
bool defaultNan,
837 fpType op1, fpType op2)
const;
839 template <
class fpType>
841 ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3,
842 fpType (*func)(fpType, fpType, fpType),
843 bool flush,
bool defaultNan, uint32_t
rMode)
const;
845 template <
class fpType>
847 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
848 fpType (*func)(fpType, fpType),
849 bool flush,
bool defaultNan, uint32_t
rMode)
const;
851 template <
class fpType>
853 unaryOp(FPSCR &fpscr, fpType op1,
854 fpType (*func)(fpType),
855 bool flush, uint32_t
rMode)
const;
861 if (
flags[IsLastMicroop]) {
863 }
else if (
flags[IsMicroop]) {
874 if (
flags[IsLastMicroop]) {
876 }
else if (
flags[IsMicroop]) {
888 return unaryOp(fpscr,
x,sqrtf,fpscr.fz,fpscr.rMode);
896 return unaryOp(fpscr,
x,sqrt,fpscr.fz,fpscr.rMode);
911 FpOp(mnem, _machInst, __opClass),
928 FpOp(mnem, _machInst, __opClass),
945 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1)
963 FpOp(mnem, _machInst, __opClass),
dest(_dest),
imm(_imm)
982 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
imm(_imm)
1001 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2)
1022 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1043 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1065 FpOp(mnem, _machInst, __opClass),
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpCondCompRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _op1, RegIndex _op2, ConditionCode _condCode, uint8_t _defCc)
FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, ConditionCode _condCode)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void advancePC(ThreadContext *tc) const override
void advancePC(PCStateBase &pcState) const override
float fpSqrt(FPSCR fpscr, float x) const
uint32_t dblLow(double val) const
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
fpType processNans(FPSCR &fpscr, bool &done, bool defaultNan, fpType op1, fpType op2) const
uint32_t dblHi(double val) const
virtual double doOp(double op1) const
fpType ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, fpType(*func)(fpType, fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
virtual float doOp(float op1) const
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
virtual double doOp(double op1, double op2) const
double fpSqrt(FPSCR fpscr, double x) const
FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
virtual float doOp(float op1, float op2) const
double dbl(uint32_t low, uint32_t high) const
FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpRegRegRegCondOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, ConditionCode _cond, VfpMicroMode mode=VfpNotAMicroop)
FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, RegIndex _op3, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Base class for predicated macro-operations.
Base class for predicated integer operations.
static bool inScalarBank(RegIndex idx)
void nextIdxs(RegIndex &dest, RegIndex &op1, RegIndex &op2)
RegIndex addStride(RegIndex idx, unsigned stride)
VfpMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, bool _wide)
std::bitset< Num_Flags > flags
Flag values for this instruction.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual const PCStateBase & pcState() const =0
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
uint32_t unsignedRecipEstimate(uint32_t op)
static uint32_t fpToBits(float)
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
static uint32_t highFromDouble(double val)
static double fpMulD(double a, double b)
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
static T fpRIntX(T a, FPSCR &fpscr)
static const uint32_t FpscrExcMask
static float fpRSqrtsS(float a, float b)
static float fpDivS(float a, float b)
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
static T fpMulX(T a, T b)
static float fpRecpsS(float a, float b)
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
uint32_t unsignedRSqrtEstimate(uint32_t op)
VfpSavedState prepFpState(uint32_t rMode)
float fixFpDFpSDest(FPSCR fpscr, double val)
static float fpMulS(float a, float b)
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
double fixFpSFpDDest(FPSCR fpscr, float val)
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
static T fpMinNum(T a, T b)
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
static uint32_t lowFromDouble(double val)
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Bitfield< 21, 20 > stride
static float bitsToFp(uint64_t, float)
static T fpMulAdd(T op1, T op2, T addend)
static double fpAddD(double a, double b)
static float fpSubS(float a, float b)
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
static double fpSubD(double a, double b)
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
static T fpRSqrts(T a, T b)
static bool isSnan(fpType val)
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
static void setFPExceptions(int exceptions)
static float fpAddS(float a, float b)
static double makeDouble(uint32_t low, uint32_t high)
static void vfpFlushToZero(FPSCR &fpscr, fpType &op)
static double fpDivD(double a, double b)
uint64_t vfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool useRmode=true, VfpRoundingMode roundMode=VfpRoundZero, bool aarch64=false)
static void setVfpMicroFlags(VfpMicroMode mode, T &flags)
static T fpRecps(T a, T b)
float fprSqrtEstimate(FPSCR &fpscr, float op)
float fpRecipEstimate(FPSCR &fpscr, float op)
static T fpMaxNum(T a, T b)
FloatType fmin(FloatType a, FloatType b)
FloatType fmax(FloatType a, FloatType b)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
constexpr bool isnan(gem5::AMDGPU::fp16_e5m10_info a)