vfp.hh revision 7430
12SN/A/*
214045Snikos.nikoleris@arm.com * Copyright (c) 2010 ARM Limited
311932Ssascha.bischoff@arm.com * All rights reserved
411932Ssascha.bischoff@arm.com *
511932Ssascha.bischoff@arm.com * The license below extends only to copyright in the software and shall
611932Ssascha.bischoff@arm.com * not be construed as granting a license to any other intellectual
711932Ssascha.bischoff@arm.com * property including but not limited to intellectual property relating
811932Ssascha.bischoff@arm.com * to a hardware implementation of the functionality of the software
911932Ssascha.bischoff@arm.com * licensed hereunder.  You may use the software subject to the license
1011932Ssascha.bischoff@arm.com * terms below provided that you ensure that this notice is replicated
1111932Ssascha.bischoff@arm.com * unmodified and in its entirety in all distributions of the software,
1211932Ssascha.bischoff@arm.com * modified or unmodified, in source code or in binary form.
1311932Ssascha.bischoff@arm.com *
141762SN/A * Redistribution and use in source and binary forms, with or without
152SN/A * modification, are permitted provided that the following conditions are
162SN/A * met: redistributions of source code must retain the above copyright
172SN/A * notice, this list of conditions and the following disclaimer;
182SN/A * redistributions in binary form must reproduce the above copyright
192SN/A * notice, this list of conditions and the following disclaimer in the
202SN/A * documentation and/or other materials provided with the distribution;
212SN/A * neither the name of the copyright holders nor the names of its
222SN/A * contributors may be used to endorse or promote products derived from
232SN/A * this software without specific prior written permission.
242SN/A *
252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362SN/A *
372SN/A * Authors: Gabe Black
382SN/A */
392665Ssaidi@eecs.umich.edu
402665Ssaidi@eecs.umich.edu#ifndef __ARCH_ARM_INSTS_VFP_HH__
412665Ssaidi@eecs.umich.edu#define __ARCH_ARM_INSTS_VFP_HH__
4212226Sgiacomo.travaglini@arm.com
432SN/A#include "arch/arm/insts/misc.hh"
442SN/A#include "arch/arm/miscregs.hh"
451112SN/A#include <fenv.h>
461112SN/A#include <cmath>
472SN/A
4811800Sbrandon.potter@amd.comnamespace ArmISA
4912226Sgiacomo.travaglini@arm.com{
5012226Sgiacomo.travaglini@arm.com
5112226Sgiacomo.travaglini@arm.comenum VfpMicroMode {
5212226Sgiacomo.travaglini@arm.com    VfpNotAMicroop,
5312226Sgiacomo.travaglini@arm.com    VfpMicroop,
5412226Sgiacomo.travaglini@arm.com    VfpFirstMicroop,
552SN/A    VfpLastMicroop
562SN/A};
572SN/A
582SN/Atemplate<class T>
592SN/Astatic inline void
602SN/AsetVfpMicroFlags(VfpMicroMode mode, T &flags)
612SN/A{
622SN/A    switch (mode) {
632SN/A      case VfpMicroop:
642SN/A        flags[StaticInst::IsMicroop] = true;
652SN/A        break;
662SN/A      case VfpFirstMicroop:
672SN/A        flags[StaticInst::IsMicroop] =
682SN/A            flags[StaticInst::IsFirstMicroop] = true;
692SN/A        break;
702SN/A      case VfpLastMicroop:
712SN/A        flags[StaticInst::IsMicroop] =
722SN/A            flags[StaticInst::IsLastMicroop] = true;
732SN/A        break;
742SN/A      case VfpNotAMicroop:
752SN/A        break;
762SN/A    }
772SN/A    if (mode == VfpMicroop || mode == VfpFirstMicroop) {
782SN/A        flags[StaticInst::IsDelayedCommit] = true;
794661Sksewell@umich.edu    }
804661Sksewell@umich.edu}
814661Sksewell@umich.edu
824661Sksewell@umich.eduenum FeExceptionBit
834661Sksewell@umich.edu{
844661Sksewell@umich.edu    FeDivByZero = FE_DIVBYZERO,
854661Sksewell@umich.edu    FeInexact = FE_INEXACT,
864661Sksewell@umich.edu    FeInvalid = FE_INVALID,
874661Sksewell@umich.edu    FeOverflow = FE_OVERFLOW,
884661Sksewell@umich.edu    FeUnderflow = FE_UNDERFLOW,
894661Sksewell@umich.edu    FeAllExceptions = FE_ALL_EXCEPT
903814Ssaidi@eecs.umich.edu};
913814Ssaidi@eecs.umich.edu
923814Ssaidi@eecs.umich.eduenum FeRoundingMode
933814Ssaidi@eecs.umich.edu{
943814Ssaidi@eecs.umich.edu    FeRoundDown = FE_DOWNWARD,
953814Ssaidi@eecs.umich.edu    FeRoundNearest = FE_TONEAREST,
963814Ssaidi@eecs.umich.edu    FeRoundZero = FE_TOWARDZERO,
973814Ssaidi@eecs.umich.edu    FeRoundUpward = FE_UPWARD
983814Ssaidi@eecs.umich.edu};
993814Ssaidi@eecs.umich.edu
1003814Ssaidi@eecs.umich.eduenum VfpRoundingMode
1014070Ssaidi@eecs.umich.edu{
1024070Ssaidi@eecs.umich.edu    VfpRoundNearest = 0,
1034070Ssaidi@eecs.umich.edu    VfpRoundUpward = 1,
1044070Ssaidi@eecs.umich.edu    VfpRoundDown = 2,
1054070Ssaidi@eecs.umich.edu    VfpRoundZero = 3
1064070Ssaidi@eecs.umich.edu};
1073814Ssaidi@eecs.umich.edu
1082SN/Atemplate <class fpType>
1092SN/Astatic inline bool
1102SN/AflushToZero(fpType &op)
1112SN/A{
11210537Sandreas.hansson@arm.com    fpType junk = 0.0;
1132SN/A    if (std::fpclassify(op) == FP_SUBNORMAL) {
1142SN/A        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
1152SN/A        op = bitsToFp(fpToBits(op) & bitMask, junk);
1162SN/A        return true;
1172SN/A    }
1182SN/A    return false;
1193422Sgblack@eecs.umich.edu}
1203422Sgblack@eecs.umich.edu
1213422Sgblack@eecs.umich.edutemplate <class fpType>
1223422Sgblack@eecs.umich.edustatic inline bool
1233422Sgblack@eecs.umich.eduflushToZero(fpType &op1, fpType &op2)
1243422Sgblack@eecs.umich.edu{
1253422Sgblack@eecs.umich.edu    bool flush1 = flushToZero(op1);
1263422Sgblack@eecs.umich.edu    bool flush2 = flushToZero(op2);
1274425Ssaidi@eecs.umich.edu    return flush1 || flush2;
1283422Sgblack@eecs.umich.edu}
1294425Ssaidi@eecs.umich.edu
1303422Sgblack@eecs.umich.edutemplate <class fpType>
1313422Sgblack@eecs.umich.edustatic inline void
1323422Sgblack@eecs.umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op)
1334661Sksewell@umich.edu{
1344661Sksewell@umich.edu    if (fpscr.fz == 1 && flushToZero(op)) {
1354661Sksewell@umich.edu        fpscr.idc = 1;
1364661Sksewell@umich.edu    }
1374661Sksewell@umich.edu}
1384661Sksewell@umich.edu
1394661Sksewell@umich.edutemplate <class fpType>
1404661Sksewell@umich.edustatic inline void
1414661Sksewell@umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
1424661Sksewell@umich.edu{
1434661Sksewell@umich.edu    vfpFlushToZero(fpscr, op1);
1443422Sgblack@eecs.umich.edu    vfpFlushToZero(fpscr, op2);
1453422Sgblack@eecs.umich.edu}
1463422Sgblack@eecs.umich.edu
1473422Sgblack@eecs.umich.edustatic inline uint32_t
1483422Sgblack@eecs.umich.edufpToBits(float fp)
1493422Sgblack@eecs.umich.edu{
1503422Sgblack@eecs.umich.edu    union
1513422Sgblack@eecs.umich.edu    {
1523422Sgblack@eecs.umich.edu        float fp;
1533422Sgblack@eecs.umich.edu        uint32_t bits;
1543422Sgblack@eecs.umich.edu    } val;
1554661Sksewell@umich.edu    val.fp = fp;
1564661Sksewell@umich.edu    return val.bits;
1574661Sksewell@umich.edu}
1584661Sksewell@umich.edu
1594661Sksewell@umich.edustatic inline uint64_t
1604661Sksewell@umich.edufpToBits(double fp)
1614661Sksewell@umich.edu{
1624661Sksewell@umich.edu    union
16312226Sgiacomo.travaglini@arm.com    {
16412226Sgiacomo.travaglini@arm.com        double fp;
16512226Sgiacomo.travaglini@arm.com        uint64_t bits;
16612226Sgiacomo.travaglini@arm.com    } val;
16712226Sgiacomo.travaglini@arm.com    val.fp = fp;
16812226Sgiacomo.travaglini@arm.com    return val.bits;
16912226Sgiacomo.travaglini@arm.com}
17012226Sgiacomo.travaglini@arm.com
17112226Sgiacomo.travaglini@arm.comstatic inline float
17212226Sgiacomo.travaglini@arm.combitsToFp(uint64_t bits, float junk)
17312226Sgiacomo.travaglini@arm.com{
17412226Sgiacomo.travaglini@arm.com    union
17512226Sgiacomo.travaglini@arm.com    {
17612226Sgiacomo.travaglini@arm.com        float fp;
17712226Sgiacomo.travaglini@arm.com        uint32_t bits;
17812226Sgiacomo.travaglini@arm.com    } val;
17912226Sgiacomo.travaglini@arm.com    val.bits = bits;
18012226Sgiacomo.travaglini@arm.com    return val.fp;
18112226Sgiacomo.travaglini@arm.com}
18212226Sgiacomo.travaglini@arm.com
18312226Sgiacomo.travaglini@arm.comstatic inline double
18412226Sgiacomo.travaglini@arm.combitsToFp(uint64_t bits, double junk)
18513824SAndrea.Mondelli@ucf.edu{
18612226Sgiacomo.travaglini@arm.com    union
18712226Sgiacomo.travaglini@arm.com    {
18812226Sgiacomo.travaglini@arm.com        double fp;
18912226Sgiacomo.travaglini@arm.com        uint64_t bits;
19012226Sgiacomo.travaglini@arm.com    } val;
19112226Sgiacomo.travaglini@arm.com    val.bits = bits;
1924103Ssaidi@eecs.umich.edu    return val.fp;
1934103Ssaidi@eecs.umich.edu}
1944103Ssaidi@eecs.umich.edu
1954103Ssaidi@eecs.umich.edutypedef int VfpSavedState;
1964103Ssaidi@eecs.umich.edu
1974103Ssaidi@eecs.umich.eduVfpSavedState prepFpState(uint32_t rMode);
1984103Ssaidi@eecs.umich.eduvoid finishVfp(FPSCR &fpscr, VfpSavedState state);
1994103Ssaidi@eecs.umich.edu
2004103Ssaidi@eecs.umich.edutemplate <class fpType>
2014244Ssaidi@eecs.umich.edufpType fixDest(FPSCR fpscr, fpType val, fpType op1);
2024244Ssaidi@eecs.umich.edu
2034244Ssaidi@eecs.umich.edutemplate <class fpType>
2044244Ssaidi@eecs.umich.edufpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
2054244Ssaidi@eecs.umich.edu
2064244Ssaidi@eecs.umich.edutemplate <class fpType>
2074103Ssaidi@eecs.umich.edufpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
2084103Ssaidi@eecs.umich.edu
2094103Ssaidi@eecs.umich.edufloat fixFpDFpSDest(FPSCR fpscr, double val);
2106274Sgblack@eecs.umich.edudouble fixFpSFpDDest(FPSCR fpscr, float val);
2116274Sgblack@eecs.umich.edu
2126274Sgblack@eecs.umich.edufloat vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top);
2136274Sgblack@eecs.umich.edufloat vcvtFpHFpS(FPSCR &fpscr, float op, bool top);
2146274Sgblack@eecs.umich.edu
2156274Sgblack@eecs.umich.edustatic inline double
2166274Sgblack@eecs.umich.edumakeDouble(uint32_t low, uint32_t high)
2176274Sgblack@eecs.umich.edu{
2186274Sgblack@eecs.umich.edu    double junk = 0.0;
2196274Sgblack@eecs.umich.edu    return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
2206274Sgblack@eecs.umich.edu}
2216274Sgblack@eecs.umich.edu
2226274Sgblack@eecs.umich.edustatic inline uint32_t
2236274Sgblack@eecs.umich.edulowFromDouble(double val)
2246274Sgblack@eecs.umich.edu{
2256274Sgblack@eecs.umich.edu    return fpToBits(val);
2266274Sgblack@eecs.umich.edu}
22710400Sstephan.diestelhorst@arm.com
22810400Sstephan.diestelhorst@arm.comstatic inline uint32_t
22910400Sstephan.diestelhorst@arm.comhighFromDouble(double val)
23010400Sstephan.diestelhorst@arm.com{
23110400Sstephan.diestelhorst@arm.com    return fpToBits(val) >> 32;
23210400Sstephan.diestelhorst@arm.com}
23310400Sstephan.diestelhorst@arm.com
23410400Sstephan.diestelhorst@arm.comuint64_t vfpFpSToFixed(float val, bool isSigned, bool half,
23510400Sstephan.diestelhorst@arm.com                       uint8_t imm, bool rzero = true);
23610400Sstephan.diestelhorst@arm.comfloat vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm);
23710400Sstephan.diestelhorst@arm.comfloat vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm);
23810400Sstephan.diestelhorst@arm.com
23910400Sstephan.diestelhorst@arm.comuint64_t vfpFpDToFixed(double val, bool isSigned, bool half,
24010400Sstephan.diestelhorst@arm.com                       uint8_t imm, bool rzero = true);
24110400Sstephan.diestelhorst@arm.comdouble vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm);
24210400Sstephan.diestelhorst@arm.comdouble vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm);
24310400Sstephan.diestelhorst@arm.com
24410400Sstephan.diestelhorst@arm.comclass VfpMacroOp : public PredMacroOp
24510400Sstephan.diestelhorst@arm.com{
24610400Sstephan.diestelhorst@arm.com  public:
24710400Sstephan.diestelhorst@arm.com    static bool
24810400Sstephan.diestelhorst@arm.com    inScalarBank(IntRegIndex idx)
24910400Sstephan.diestelhorst@arm.com    {
25010400Sstephan.diestelhorst@arm.com        return (idx % 32) < 8;
25110400Sstephan.diestelhorst@arm.com    }
25210400Sstephan.diestelhorst@arm.com
25310400Sstephan.diestelhorst@arm.com  protected:
25410400Sstephan.diestelhorst@arm.com    bool wide;
25510400Sstephan.diestelhorst@arm.com
25610400Sstephan.diestelhorst@arm.com    VfpMacroOp(const char *mnem, ExtMachInst _machInst,
25710400Sstephan.diestelhorst@arm.com            OpClass __opClass, bool _wide) :
25810400Sstephan.diestelhorst@arm.com        PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
25910400Sstephan.diestelhorst@arm.com    {}
26011932Ssascha.bischoff@arm.com
26111932Ssascha.bischoff@arm.com    IntRegIndex addStride(IntRegIndex idx, unsigned stride);
26211932Ssascha.bischoff@arm.com    void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
26311932Ssascha.bischoff@arm.com    void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
26411932Ssascha.bischoff@arm.com    void nextIdxs(IntRegIndex &dest);
26511932Ssascha.bischoff@arm.com};
26611932Ssascha.bischoff@arm.com
26711932Ssascha.bischoff@arm.comstatic inline float
26811932Ssascha.bischoff@arm.comfpAddS(float a, float b)
26911932Ssascha.bischoff@arm.com{
27011932Ssascha.bischoff@arm.com    return a + b;
27111932Ssascha.bischoff@arm.com}
27211932Ssascha.bischoff@arm.com
27311932Ssascha.bischoff@arm.comstatic inline double
27411932Ssascha.bischoff@arm.comfpAddD(double a, double b)
27511932Ssascha.bischoff@arm.com{
27611932Ssascha.bischoff@arm.com    return a + b;
27711932Ssascha.bischoff@arm.com}
27811932Ssascha.bischoff@arm.com
27911932Ssascha.bischoff@arm.comstatic inline float
28011932Ssascha.bischoff@arm.comfpSubS(float a, float b)
28111932Ssascha.bischoff@arm.com{
28211932Ssascha.bischoff@arm.com    return a - b;
28311932Ssascha.bischoff@arm.com}
28411932Ssascha.bischoff@arm.com
28513531Sjairo.balart@metempsy.comstatic inline double
28613531Sjairo.balart@metempsy.comfpSubD(double a, double b)
28713531Sjairo.balart@metempsy.com{
28813531Sjairo.balart@metempsy.com    return a - b;
28913531Sjairo.balart@metempsy.com}
29013531Sjairo.balart@metempsy.com
29113531Sjairo.balart@metempsy.comstatic inline float
29213531Sjairo.balart@metempsy.comfpDivS(float a, float b)
29313531Sjairo.balart@metempsy.com{
29413531Sjairo.balart@metempsy.com    return a / b;
29513531Sjairo.balart@metempsy.com}
29614045Snikos.nikoleris@arm.com
29714045Snikos.nikoleris@arm.comstatic inline double
29814045Snikos.nikoleris@arm.comfpDivD(double a, double b)
29914045Snikos.nikoleris@arm.com{
30014045Snikos.nikoleris@arm.com    return a / b;
30114045Snikos.nikoleris@arm.com}
30214045Snikos.nikoleris@arm.com
30314045Snikos.nikoleris@arm.comstatic inline float
30414045Snikos.nikoleris@arm.comfpMulS(float a, float b)
30514045Snikos.nikoleris@arm.com{
30614045Snikos.nikoleris@arm.com    return a * b;
3071112SN/A}
308
309static inline double
310fpMulD(double a, double b)
311{
312    return a * b;
313}
314
315class FpOp : public PredOp
316{
317  protected:
318    FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
319        PredOp(mnem, _machInst, __opClass)
320    {}
321
322    virtual float
323    doOp(float op1, float op2) const
324    {
325        panic("Unimplemented version of doOp called.\n");
326    }
327
328    virtual float
329    doOp(float op1) const
330    {
331        panic("Unimplemented version of doOp called.\n");
332    }
333
334    virtual double
335    doOp(double op1, double op2) const
336    {
337        panic("Unimplemented version of doOp called.\n");
338    }
339
340    virtual double
341    doOp(double op1) const
342    {
343        panic("Unimplemented version of doOp called.\n");
344    }
345
346    double
347    dbl(uint32_t low, uint32_t high) const
348    {
349        double junk = 0.0;
350        return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
351    }
352
353    uint32_t
354    dblLow(double val) const
355    {
356        return fpToBits(val);
357    }
358
359    uint32_t
360    dblHi(double val) const
361    {
362        return fpToBits(val) >> 32;
363    }
364
365    template <class fpType>
366    fpType
367    binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
368            fpType (*func)(fpType, fpType),
369            bool flush, uint32_t rMode) const;
370
371    template <class fpType>
372    fpType
373    unaryOp(FPSCR &fpscr, fpType op1,
374            fpType (*func)(fpType),
375            bool flush, uint32_t rMode) const;
376};
377
378class FpRegRegOp : public FpOp
379{
380  protected:
381    IntRegIndex dest;
382    IntRegIndex op1;
383
384    FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
385               IntRegIndex _dest, IntRegIndex _op1,
386               VfpMicroMode mode = VfpNotAMicroop) :
387        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
388    {
389        setVfpMicroFlags(mode, flags);
390    }
391
392    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
393};
394
395class FpRegImmOp : public FpOp
396{
397  protected:
398    IntRegIndex dest;
399    uint64_t imm;
400
401    FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
402               IntRegIndex _dest, uint64_t _imm,
403               VfpMicroMode mode = VfpNotAMicroop) :
404        FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
405    {
406        setVfpMicroFlags(mode, flags);
407    }
408
409    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
410};
411
412class FpRegRegImmOp : public FpOp
413{
414  protected:
415    IntRegIndex dest;
416    IntRegIndex op1;
417    uint64_t imm;
418
419    FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
420                  IntRegIndex _dest, IntRegIndex _op1,
421                  uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
422        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
423    {
424        setVfpMicroFlags(mode, flags);
425    }
426
427    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
428};
429
430class FpRegRegRegOp : public FpOp
431{
432  protected:
433    IntRegIndex dest;
434    IntRegIndex op1;
435    IntRegIndex op2;
436
437    FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
438                  IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
439                  VfpMicroMode mode = VfpNotAMicroop) :
440        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
441    {
442        setVfpMicroFlags(mode, flags);
443    }
444
445    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
446};
447
448}
449
450#endif //__ARCH_ARM_INSTS_VFP_HH__
451