Go to the documentation of this file.
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;
115 static inline float bitsToFp(uint64_t,
float);
116 static inline double bitsToFp(uint64_t,
double);
117 static inline uint32_t
fpToBits(
float);
118 static inline uint64_t
fpToBits(
double);
120 template <
class fpType>
125 if (std::fpclassify(
op) == FP_SUBNORMAL) {
126 uint64_t bitMask = 0x1ULL << (
sizeof(fpType) * 8 - 1);
133 template <
class fpType>
139 return flush1 || flush2;
142 template <
class fpType>
151 template <
class fpType>
159 static inline uint32_t
171 static inline uint64_t
207 template <
class fpType>
211 const bool single = (
sizeof(fpType) ==
sizeof(
float));
212 const uint64_t qnan =
213 single ? 0x7fc00000 : 0x7ff8000000000000ULL;
222 template <
class fpType>
223 fpType
fixDest(FPSCR fpscr, fpType
val, fpType op1);
225 template <
class fpType>
226 fpType
fixDest(FPSCR fpscr, fpType
val, fpType op1, fpType op2);
228 template <
class fpType>
229 fpType
fixDivDest(FPSCR fpscr, fpType
val, fpType op1, fpType op2);
234 uint16_t
vcvtFpSFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
236 uint16_t
vcvtFpDFpH(FPSCR &fpscr,
bool flush,
bool defaultNan,
239 float vcvtFpHFpS(FPSCR &fpscr,
bool defaultNan,
bool ahp, uint16_t
op);
240 double vcvtFpHFpD(FPSCR &fpscr,
bool defaultNan,
bool ahp, uint16_t
op);
246 return bitsToFp((uint64_t)low | ((uint64_t)
high << 32), junk);
249 static inline uint32_t
255 static inline uint32_t
264 feraiseexcept(exceptions);
267 template <
typename T>
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) {
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;
417 if ((
double)
val < 0) {
463 return (idx % 32) < 8;
470 OpClass __opClass,
bool _wide) :
475 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
476 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
480 template <
typename T>
487 template <
typename T>
530 template <
typename T>
537 template <
typename T>
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)) {
571 template <
typename T>
590 template <
typename T>
597 if (
sizeof(T) ==
sizeof(
float))
598 result = fmaf(op1, op2, addend);
600 result = fma(op1, op2, addend);
603 if (std::isnan(result) && !std::isnan(op1) &&
604 !std::isnan(op2) && !std::isnan(addend))
606 uint64_t bitMask = 0x1ULL << ((
sizeof(T) * 8) - 1);
612 template <
typename T>
619 if (rVal !=
a && !std::isnan(
a))
624 template <
typename T>
628 const bool single = (
sizeof(T) ==
sizeof(
float));
629 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
636 if (!std::signbit(
a) && std::signbit(
b))
641 template <
typename T>
649 return fpMaxNum<T>(
a,
b);
652 template <
typename T>
656 const bool single = (
sizeof(T) ==
sizeof(
float));
657 const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
664 if (std::signbit(
a) && !std::signbit(
b))
669 template <
typename T>
677 return fpMinNum<T>(
a,
b);
680 template <
typename T>
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;
702 template <
typename T>
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);
767 template <
typename T>
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");
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);
909 OpClass __opClass, IntRegIndex _op1, IntRegIndex _op2,
911 FpOp(mnem, _machInst, __opClass),
926 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
928 FpOp(mnem, _machInst, __opClass),
943 IntRegIndex _dest, IntRegIndex _op1,
945 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1)
961 IntRegIndex _dest, uint64_t _imm,
963 FpOp(mnem, _machInst, __opClass),
dest(_dest),
imm(_imm)
980 IntRegIndex _dest, IntRegIndex _op1,
982 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
imm(_imm)
999 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
1001 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2)
1019 OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1,
1022 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1041 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
1043 FpOp(mnem, _machInst, __opClass),
dest(_dest),
op1(_op1),
op2(_op2),
1062 OpClass __opClass, IntRegIndex _dest,
1063 IntRegIndex _op1, IntRegIndex _op2,
1065 FpOp(mnem, _machInst, __opClass),
1078 #endif //__ARCH_ARM_INSTS_VFP_HH__
uint32_t unsignedRSqrtEstimate(uint32_t op)
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
static T fpMinNum(T a, T b)
static T fpRecps(T a, T b)
static float bitsToFp(uint64_t, float)
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
float fixFpDFpSDest(FPSCR fpscr, double val)
double fpSqrt(FPSCR fpscr, double x) const
float fprSqrtEstimate(FPSCR &fpscr, float op)
static void setVfpMicroFlags(VfpMicroMode mode, T &flags)
static float fpRSqrtsS(float a, float b)
double dbl(uint32_t low, uint32_t high) const
static T fpMaxNum(T a, T b)
FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
static float fpMulS(float a, float b)
static double fpSubD(double a, double b)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
uint32_t dblHi(double val) const
virtual const PCStateBase & pcState() const =0
static T fpRSqrts(T a, T b)
static void setFPExceptions(int exceptions)
uint64_t vfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool useRmode=true, VfpRoundingMode roundMode=VfpRoundZero, bool aarch64=false)
static double fpAddD(double a, double b)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
static void vfpFlushToZero(FPSCR &fpscr, fpType &op)
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, IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, VfpMicroMode mode=VfpNotAMicroop)
static float fpSubS(float a, float b)
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
static const uint32_t FpscrExcMask
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, IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, ConditionCode _cond, VfpMicroMode mode=VfpNotAMicroop)
virtual float doOp(float op1) const
fpType processNans(FPSCR &fpscr, bool &done, bool defaultNan, fpType op1, fpType op2) const
FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
VfpMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, bool _wide)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
static float fpDivS(float a, float b)
FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, IntRegIndex _op3, VfpMicroMode mode=VfpNotAMicroop)
static double makeDouble(uint32_t low, uint32_t high)
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
ThreadContext is the external interface to all thread state for anything outside of the CPU.
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
FpCondCompRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _op1, IntRegIndex _op2, ConditionCode _condCode, uint8_t _defCc)
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
virtual float doOp(float op1, float op2) const
FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, ConditionCode _condCode)
static T fpMulAdd(T op1, T op2, T addend)
std::bitset< Num_Flags > flags
Flag values for this instruction.
IntRegIndex addStride(IntRegIndex idx, unsigned stride)
uint32_t dblLow(double val) const
static float fpAddS(float a, float b)
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
void advancePC(ThreadContext *tc) const override
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
static T fpRIntX(T a, FPSCR &fpscr)
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
static uint32_t fpToBits(float)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
static bool inScalarBank(IntRegIndex idx)
Base class for predicated macro-operations.
virtual double doOp(double op1) const
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
static T fpMulX(T a, T b)
virtual double doOp(double op1, double op2) const
float fpRecipEstimate(FPSCR &fpscr, float op)
static uint32_t highFromDouble(double val)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
VfpSavedState prepFpState(uint32_t rMode)
FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void advancePC(PCStateBase &pcState) const override
static double fpMulD(double a, double b)
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
fpType ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, fpType(*func)(fpType, fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
uint32_t unsignedRecipEstimate(uint32_t op)
static float fpRecpsS(float a, float b)
Base class for predicated integer operations.
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
static bool isSnan(fpType val)
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
static uint32_t lowFromDouble(double val)
float fpSqrt(FPSCR fpscr, float x) const
Bitfield< 21, 20 > stride
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, VfpMicroMode mode=VfpNotAMicroop)
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
#define panic(...)
This implements a cprintf based panic() function.
static double fpDivD(double a, double b)
double fixFpSFpDDest(FPSCR fpscr, float val)
Generated on Wed May 4 2022 12:13:48 for gem5 by doxygen 1.8.17