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);
124 uint16_t exponent =
bits(__x, 14, 10);
125 uint16_t fraction =
bits(__x, 9, 0);
134 }
else if (exponent == 0x1F) {
145template <
class fpType>
150 if (std::fpclassify(
op) == FP_SUBNORMAL) {
151 uint64_t bitMask = 0x1ULL << (
sizeof(fpType) * 8 - 1);
168template <
class fpType>
174 return flush1 || flush2;
177template <
class fpType>
194template <
class fpType>
202static inline uint32_t
214static inline uint64_t
250template <
class fpType>
254 const bool single = (
sizeof(fpType) ==
sizeof(float));
255 const uint64_t qnan =
256 single ? 0x7fc00000 : 0x7ff8000000000000ULL;
265template <
class fpType>
268template <
class fpType>
269fpType
fixDest(FPSCR fpscr, fpType
val, fpType op1, fpType op2);
271template <
class fpType>
277uint16_t
vcvtFpSFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
279uint16_t
vcvtFpDFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
283double vcvtFpHFpD(FPSCR &fpscr,
bool defaultNan,
bool ahp, uint16_t
op);
289 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
292static inline uint32_t
298static inline uint32_t
307 feraiseexcept(exceptions);
318 bool roundAwayFix =
false;
321 rmode = fegetround();
344 panic(
"Unsupported roundMode %d\n", roundMode);
347 __asm__ __volatile__(
"" :
"=m" (rmode) :
"m" (rmode));
350 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
353 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
356 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
360 int fpType = std::fpclassify(
val);
361 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
362 if (fpType == FP_NAN) {
366 }
else if (origVal !=
val) {
369 if (origVal -
val > 0.5)
371 else if (
val - origVal > 0.5)
380 volatile T error =
val;
383 if ( (error > 0.5) ||
384 ((error == 0.5) && (
val >= 0)) )
399 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
402 bool outOfRange =
false;
403 int64_t result = (int64_t)
val;
408 finalVal = (int16_t)
val;
409 }
else if (
width == 32) {
410 finalVal =(int32_t)
val;
411 }
else if (
width == 64) {
419 if ((
double)
val < minVal) {
424 if ((
double)
val > maxVal) {
429 bool isNeg =
val < 0;
434 outOfRange = ((uint64_t) result >> (
width - 1)) !=
441 outOfRange |=
val < result;
443 finalVal = 1LL << (
width-1);
446 outOfRange |=
val > result;
461 if ((
double)
val < 0) {
489 bool roundAwayFix =
false;
492 rmode = fegetround();
515 panic(
"Unsupported roundMode %d\n", roundMode);
518 __asm__ __volatile__(
"" :
"=m" (rmode) :
"m" (rmode));
519 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
522 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
525 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
532 int fpType = std::fpclassify(
val);
533 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
534 if (fpType == FP_NAN) {
539 bool single = (
sizeof(T) ==
sizeof(float));
540 uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
546 }
else if (origVal !=
val) {
549 if (origVal -
val > 0.5)
551 else if (
val - origVal > 0.5)
560 volatile T error =
val;
563 if ( (error > 0.5) ||
564 ((error == 0.5) && (
val >= 0)) )
581 fpType = std::fpclassify(
val);
582 if (fpType == FP_ZERO) {
583 bool single = (
sizeof(T) ==
sizeof(float));
584 uint64_t
mask = single ? 0x80000000 : 0x8000000000000000ULL;
623 return (idx % 32) < 8;
630 OpClass __opClass,
bool _wide) :
704 const bool single = (
sizeof(T) ==
sizeof(float));
716 bool inf1 = (std::fpclassify(
a) == FP_INFINITE);
717 bool inf2 = (std::fpclassify(
b) == FP_INFINITE);
718 bool zero1 = (std::fpclassify(
a) == FP_ZERO);
719 bool zero2 = (std::fpclassify(
b) == FP_ZERO);
720 if ((inf1 && zero2) || (zero1 && inf2)) {
757 if (
sizeof(T) ==
sizeof(
float))
758 result = fmaf(op1, op2, addend);
760 result = fma(op1, op2, addend);
766 uint64_t bitMask = 0x1ULL << ((
sizeof(T) * 8) - 1);
788 const bool single = (
sizeof(T) ==
sizeof(float));
789 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
796 if (!std::signbit(
a) && std::signbit(
b))
816 const bool single = (
sizeof(T) ==
sizeof(float));
817 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
824 if (std::signbit(
a) && !std::signbit(
b))
844 int fpClassA = std::fpclassify(
a);
845 int fpClassB = std::fpclassify(
b);
849 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
850 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
854 fpClassAxB = std::fpclassify(aXb);
855 if (fpClassAxB == FP_SUBNORMAL) {
859 return (3.0 - (
a *
b)) / 2.0;
866 int fpClassA = std::fpclassify(
a);
867 int fpClassB = std::fpclassify(
b);
871 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
872 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
876 fpClassAxB = std::fpclassify(aXb);
877 if (fpClassAxB == FP_SUBNORMAL) {
881 return 2.0 - (
a *
b);
888 int fpClassA = std::fpclassify(
a);
889 int fpClassB = std::fpclassify(
b);
893 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
894 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
898 fpClassAxB = std::fpclassify(aXb);
899 if (fpClassAxB == FP_SUBNORMAL) {
903 return (3.0 - (
a *
b)) / 2.0;
909 int fpClassA = std::fpclassify(
a);
910 int fpClassB = std::fpclassify(
b);
914 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
915 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
919 fpClassAxB = std::fpclassify(aXb);
920 if (fpClassAxB == FP_SUBNORMAL) {
924 return 2.0 - (
a *
b);
933 if (
a -
val == 0.5) {
934 if ( (((
int)
a) & 1) == 0 )
val += 1.0;
936 else if (
a -
val == -0.5) {
937 if ( (((
int)
a) & 1) == 0 )
val -= 1.0;
948 PredOp(mnem, _machInst, __opClass)
952 doOp(
float op1,
float op2)
const
954 panic(
"Unimplemented version of doOp called.\n");
960 panic(
"Unimplemented version of doOp called.\n");
964 doOp(
double op1,
double op2)
const
966 panic(
"Unimplemented version of doOp called.\n");
972 panic(
"Unimplemented version of doOp called.\n");
976 dbl(uint32_t low, uint32_t high)
const
979 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
994 template <
class fpType>
996 processNans(FPSCR &fpscr,
bool &done,
bool defaultNan,
997 fpType op1, fpType op2)
const;
999 template <
class fpType>
1001 ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3,
1002 fpType (*func)(fpType, fpType, fpType),
1003 bool flush,
bool defaultNan, uint32_t
rMode)
const;
1005 template <
class fpType>
1007 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
1008 fpType (*func)(fpType, fpType),
1009 bool flush,
bool defaultNan, uint32_t
rMode)
const;
1011 template <
class fpType>
1013 unaryOp(FPSCR &fpscr, fpType op1,
1014 fpType (*func)(fpType),
1015 bool flush, uint32_t
rMode)
const;
1021 if (
flags[IsLastMicroop]) {
1023 }
else if (
flags[IsMicroop]) {
1034 if (
flags[IsLastMicroop]) {
1036 }
else if (
flags[IsMicroop]) {
1048 return unaryOp(fpscr,
x,sqrtf,fpscr.fz,fpscr.rMode);
1056 return unaryOp(fpscr,
x,sqrt,fpscr.fz,fpscr.rMode);
1071 FpOp(mnem, _machInst, __opClass),
1088 FpOp(mnem, _machInst, __opClass),
1105 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1)
1123 FpOp(mnem, _machInst, __opClass),
dest(_dest),
imm(_imm)
1142 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
imm(_imm)
1161 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2)
1182 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1203 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1225 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.
PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
Constructor.
PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
Constructor.
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)
uint16_t fpRecipEstimateFpH(FPSCR &fpscr, uint16_t op)
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
T GEM5_NO_OPTIMIZE vfpFpRint(T val, bool exact, bool defaultNan, bool useRmode=true, VfpRoundingMode roundMode=VfpRoundZero)
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)
uint16_t fprSqrtEstimateFpH(FPSCR &fpscr, uint16_t op)
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 bool flushToZeroFpH(uint16_t &op)
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)
constexpr int fpclassifyFpH(uint16_t __x)
static T fpMulAdd(T op1, T op2, T addend)
static double fpAddD(double a, double b)
static float fpSubS(float a, float b)
FPSCR fpVASimdCvtFPSCRValue(const FPSCR &fpscr)
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
static double fpSubD(double a, double b)
uint64_t GEM5_NO_OPTIMIZE vfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool useRmode=true, VfpRoundingMode roundMode=VfpRoundZero, bool aarch64=false)
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
static T fpRSqrts(T a, T b)
static bool isSnan(fpType val)
static void vfpFlushToZeroFpH(FPSCR &fpscr, uint16_t &op)
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)
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)
FPSCR fpRestoreFPSCRValue(const FPSCR fpscr_exec, const FPSCR &fpscr)
FPSCR fpVASimdFPSCRValue(const FPSCR &fpscr)
static T fpMaxNum(T a, T b)
FloatType fmin(FloatType a, FloatType b)
FloatType fmax(FloatType a, FloatType b)
Copyright (c) 2024 Arm Limited 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)