12068SN/A// -*- mode:c++ -*-
22068SN/A
32068SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
42068SN/A// All rights reserved.
52068SN/A//
62068SN/A// Redistribution and use in source and binary forms, with or without
72068SN/A// modification, are permitted provided that the following conditions are
82068SN/A// met: redistributions of source code must retain the above copyright
92068SN/A// notice, this list of conditions and the following disclaimer;
102068SN/A// redistributions in binary form must reproduce the above copyright
112068SN/A// notice, this list of conditions and the following disclaimer in the
122068SN/A// documentation and/or other materials provided with the distribution;
132068SN/A// neither the name of the copyright holders nor the names of its
142068SN/A// contributors may be used to endorse or promote products derived from
152068SN/A// this software without specific prior written permission.
162068SN/A//
172068SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182068SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192068SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202068SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212068SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222068SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232068SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242068SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252068SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262068SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272068SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu//
292665Ssaidi@eecs.umich.edu// Authors: Steve Reinhardt
302068SN/A
312649Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////
322649Ssaidi@eecs.umich.edu//
332649Ssaidi@eecs.umich.edu// Floating-point instructions
342649Ssaidi@eecs.umich.edu//
357799Sgblack@eecs.umich.edu//      Note that many FP-type instructions which do not support all the
367799Sgblack@eecs.umich.edu//      various rounding & trapping modes use the simpler format
377799Sgblack@eecs.umich.edu//      BasicOperateWithNopCheck.
382649Ssaidi@eecs.umich.edu//
392649Ssaidi@eecs.umich.edu
402068SN/Aoutput exec {{
412068SN/A    /// Check "FP enabled" machine status bit.  Called when executing any FP
422068SN/A    /// instruction in full-system mode.
432090SN/A    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
442090SN/A    /// if not.  Non-full-system mode: always returns NoFault.
4512234Sgabeblack@google.com    inline Fault checkFpEnableFault(ExecContext *xc)
462068SN/A    {
477799Sgblack@eecs.umich.edu        Fault fault = NoFault;  // dummy... this ipr access should not fault
488738Sgblack@eecs.umich.edu        if (FullSystem && !ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
4910474Sandreas.hansson@arm.com            fault = std::make_shared<FloatEnableFault>();
502068SN/A        }
512068SN/A        return fault;
522068SN/A    }
5312234Sgabeblack@google.com    inline Fault checkVectorEnableFault(ExecContext *xc) {
5412110SRekai.GonzalezAlberquilla@arm.com        return std::make_shared<VectorEnableFault>();
5512110SRekai.GonzalezAlberquilla@arm.com    }
562068SN/A}};
572068SN/A
582068SN/Aoutput header {{
592068SN/A    /**
602068SN/A     * Base class for general floating-point instructions.  Includes
612068SN/A     * support for various Alpha rounding and trapping modes.  Only FP
622068SN/A     * instructions that require this support are derived from this
632068SN/A     * class; the rest derive directly from AlphaStaticInst.
642068SN/A     */
652068SN/A    class AlphaFP : public AlphaStaticInst
662068SN/A    {
672068SN/A      public:
682068SN/A        /// Alpha FP rounding modes.
692068SN/A        enum RoundingMode {
707799Sgblack@eecs.umich.edu            Chopped = 0,        ///< round toward zero
712068SN/A            Minus_Infinity = 1, ///< round toward minus infinity
727799Sgblack@eecs.umich.edu            Normal = 2,         ///< round to nearest (default)
737799Sgblack@eecs.umich.edu            Dynamic = 3,        ///< use FPCR setting (in instruction)
747799Sgblack@eecs.umich.edu            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
752068SN/A        };
762068SN/A
772068SN/A        /// Alpha FP trapping modes.
782068SN/A        /// For instructions that produce integer results, the
792068SN/A        /// "Underflow Enable" modes really mean "Overflow Enable", and
802068SN/A        /// the assembly modifier is V rather than U.
812068SN/A        enum TrappingMode {
822068SN/A            /// default: nothing enabled
837799Sgblack@eecs.umich.edu            Imprecise = 0,                 ///< no modifier
842068SN/A            /// underflow/overflow traps enabled, inexact disabled
857799Sgblack@eecs.umich.edu            Underflow_Imprecise = 1,       ///< /U or /V
867799Sgblack@eecs.umich.edu            Underflow_Precise = 5,         ///< /SU or /SV
872068SN/A            /// underflow/overflow and inexact traps enabled
882068SN/A            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
892068SN/A        };
902068SN/A
912068SN/A      protected:
922068SN/A        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
932068SN/A        static const int alphaToC99RoundingMode[];
942068SN/A
952068SN/A        /// Map enum RoundingMode values to disassembly suffixes.
962068SN/A        static const char *roundingModeSuffix[];
972068SN/A        /// Map enum TrappingMode values to FP disassembly suffixes.
982068SN/A        static const char *fpTrappingModeSuffix[];
992068SN/A        /// Map enum TrappingMode values to integer disassembly suffixes.
1002068SN/A        static const char *intTrappingModeSuffix[];
1012068SN/A
1022068SN/A        /// This instruction's rounding mode.
1032068SN/A        RoundingMode roundingMode;
1042068SN/A        /// This instruction's trapping mode.
1052068SN/A        TrappingMode trappingMode;
1062068SN/A
1072068SN/A        /// Have we warned about this instruction's unsupported
1082068SN/A        /// rounding mode (if applicable)?
1092068SN/A        mutable bool warnedOnRounding;
1102068SN/A
1112068SN/A        /// Have we warned about this instruction's unsupported
1122068SN/A        /// trapping mode (if applicable)?
1132068SN/A        mutable bool warnedOnTrapping;
1142068SN/A
1152068SN/A        /// Constructor
1162227SN/A        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1172068SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
1182068SN/A              roundingMode((enum RoundingMode)FP_ROUNDMODE),
1192068SN/A              trappingMode((enum TrappingMode)FP_TRAPMODE),
1202068SN/A              warnedOnRounding(false),
1212068SN/A              warnedOnTrapping(false)
1222068SN/A        {
1232068SN/A        }
1242068SN/A
1252068SN/A        int getC99RoundingMode(uint64_t fpcr_val) const;
1262068SN/A
1272068SN/A        // This differs from the AlphaStaticInst version only in
1282068SN/A        // printing suffixes for non-default rounding & trapping modes.
12912616Sgabeblack@google.com        std::string generateDisassembly(
13012616Sgabeblack@google.com                Addr pc, const SymbolTable *symtab) const override;
1312068SN/A    };
1322068SN/A
1332068SN/A}};
1342068SN/A
1352068SN/A
1362068SN/Aoutput decoder {{
1372068SN/A    int
1382068SN/A    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
1392068SN/A    {
1402068SN/A        if (roundingMode == Dynamic) {
1412068SN/A            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
1422068SN/A        }
1432068SN/A        else {
1442068SN/A            return alphaToC99RoundingMode[roundingMode];
1452068SN/A        }
1462068SN/A    }
1472068SN/A
1482068SN/A    std::string
1492068SN/A    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1502068SN/A    {
1512068SN/A        std::string mnem_str(mnemonic);
1522068SN/A
1532068SN/A#ifndef SS_COMPATIBLE_DISASSEMBLY
1542068SN/A        std::string suffix("");
15512106SRekai.GonzalezAlberquilla@arm.com        suffix += ((_destRegIdx[0].isFloatReg())
1562068SN/A                   ? fpTrappingModeSuffix[trappingMode]
1572068SN/A                   : intTrappingModeSuffix[trappingMode]);
1582068SN/A        suffix += roundingModeSuffix[roundingMode];
1592068SN/A
1602068SN/A        if (suffix != "") {
1612068SN/A            mnem_str = csprintf("%s/%s", mnemonic, suffix);
1622068SN/A        }
1632068SN/A#endif
1642068SN/A
1652068SN/A        std::stringstream ss;
1662068SN/A        ccprintf(ss, "%-10s ", mnem_str.c_str());
1672068SN/A
1682068SN/A        // just print the first two source regs... if there's
1692068SN/A        // a third one, it's a read-modify-write dest (Rc),
1702068SN/A        // e.g. for CMOVxx
1712068SN/A        if (_numSrcRegs > 0) {
1722068SN/A            printReg(ss, _srcRegIdx[0]);
1732068SN/A        }
1742068SN/A        if (_numSrcRegs > 1) {
1752068SN/A            ss << ",";
1762068SN/A            printReg(ss, _srcRegIdx[1]);
1772068SN/A        }
1782068SN/A
1792068SN/A        // just print the first dest... if there's a second one,
1802068SN/A        // it's generally implicit
1812068SN/A        if (_numDestRegs > 0) {
1822068SN/A            if (_numSrcRegs > 0)
1832068SN/A                ss << ",";
1842068SN/A            printReg(ss, _destRegIdx[0]);
1852068SN/A        }
1862068SN/A
1872068SN/A        return ss.str();
1882068SN/A    }
1892068SN/A
1902068SN/A    const int AlphaFP::alphaToC99RoundingMode[] = {
1917799Sgblack@eecs.umich.edu        M5_FE_TOWARDZERO,       // Chopped
1927799Sgblack@eecs.umich.edu        M5_FE_DOWNWARD, // Minus_Infinity
1937799Sgblack@eecs.umich.edu        M5_FE_TONEAREST,        // Normal
1947799Sgblack@eecs.umich.edu        M5_FE_UPWARD    // Dynamic in inst, Plus_Infinity in FPCR
1952068SN/A    };
1962068SN/A
1972068SN/A    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
1982068SN/A    // mark invalid trapping modes, but don't fail on them, because
1992068SN/A    // you could decode anything on a misspeculated path
2002068SN/A    const char *AlphaFP::fpTrappingModeSuffix[] =
2012068SN/A        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
2022068SN/A    const char *AlphaFP::intTrappingModeSuffix[] =
2032068SN/A        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
2042068SN/A}};
2052068SN/A
2062068SN/A// FP instruction class execute method template.  Handles non-standard
2072068SN/A// rounding modes.
2082068SN/Adef template FloatingPointExecute {{
20912234Sgabeblack@google.com    Fault %(class_name)s::execute(ExecContext *xc,
2102068SN/A                                  Trace::InstRecord *traceData) const
2112068SN/A    {
2122068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2132068SN/A            warn("%s: non-standard trapping mode not supported",
2142068SN/A                 generateDisassembly(0, NULL));
2152068SN/A            warnedOnTrapping = true;
2162068SN/A        }
2172068SN/A
2182132SN/A        Fault fault = NoFault;
2192068SN/A
2202068SN/A        %(fp_enable_check)s;
2212068SN/A        %(op_decl)s;
2222068SN/A        %(op_rd)s;
2232068SN/A#if USE_FENV
2242068SN/A        if (roundingMode == Normal) {
2252068SN/A            %(code)s;
2262068SN/A        } else {
2274394Ssaidi@eecs.umich.edu            m5_fesetround(getC99RoundingMode(
2287783SGiacomo.Gabrielli@arm.com                           xc->readMiscReg(MISCREG_FPCR)));
2292068SN/A            %(code)s;
2304394Ssaidi@eecs.umich.edu            m5_fesetround(M5_FE_TONEAREST);
2312068SN/A        }
2322068SN/A#else
2332068SN/A        if (roundingMode != Normal && !warnedOnRounding) {
2342068SN/A            warn("%s: non-standard rounding mode not supported",
2352068SN/A                 generateDisassembly(0, NULL));
2362068SN/A            warnedOnRounding = true;
2372068SN/A        }
2382068SN/A        %(code)s;
2392068SN/A#endif
2402068SN/A
2412090SN/A        if (fault == NoFault) {
2422068SN/A            %(op_wb)s;
2432068SN/A        }
2442068SN/A
2452068SN/A        return fault;
2462068SN/A    }
2472068SN/A}};
2482068SN/A
2492068SN/A// FP instruction class execute method template where no dynamic
2502068SN/A// rounding mode control is needed.  Like BasicExecute, but includes
2512068SN/A// check & warning for non-standard trapping mode.
2522068SN/Adef template FPFixedRoundingExecute {{
25312234Sgabeblack@google.com    Fault %(class_name)s::execute(ExecContext *xc,
2542068SN/A                                  Trace::InstRecord *traceData) const
2552068SN/A    {
2562068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2572068SN/A            warn("%s: non-standard trapping mode not supported",
2582068SN/A                 generateDisassembly(0, NULL));
2592068SN/A            warnedOnTrapping = true;
2602068SN/A        }
2612068SN/A
2622132SN/A        Fault fault = NoFault;
2632068SN/A
2642068SN/A        %(fp_enable_check)s;
2652068SN/A        %(op_decl)s;
2662068SN/A        %(op_rd)s;
2672068SN/A        %(code)s;
2682068SN/A
2692090SN/A        if (fault == NoFault) {
2702068SN/A            %(op_wb)s;
2712068SN/A        }
2722068SN/A
2732068SN/A        return fault;
2742068SN/A    }
2752068SN/A}};
2762068SN/A
2772068SN/Adef template FloatingPointDecode {{
2782068SN/A {
2792068SN/A     AlphaStaticInst *i = new %(class_name)s(machInst);
2802068SN/A     if (FC == 31) {
2812068SN/A         i = makeNop(i);
2822068SN/A     }
2832068SN/A     return i;
2842068SN/A }
2852068SN/A}};
2862068SN/A
2872068SN/A// General format for floating-point operate instructions:
2882068SN/A// - Checks trapping and rounding mode flags.  Trapping modes
2892068SN/A//   currently unimplemented (will fail).
2902068SN/A// - Generates NOP if FC == 31.
2912068SN/Adef format FloatingPointOperate(code, *opt_args) {{
2923953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
2932068SN/A    decode_block = FloatingPointDecode.subst(iop)
2942068SN/A    header_output = BasicDeclare.subst(iop)
2952068SN/A    decoder_output = BasicConstructor.subst(iop)
2962068SN/A    exec_output = FloatingPointExecute.subst(iop)
2972068SN/A}};
2982068SN/A
2992068SN/A// Special format for cvttq where rounding mode is pre-decoded
3002068SN/Adef format FPFixedRounding(code, class_suffix, *opt_args) {{
3012068SN/A    Name += class_suffix
3023953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
3032068SN/A    decode_block = FloatingPointDecode.subst(iop)
3042068SN/A    header_output = BasicDeclare.subst(iop)
3052068SN/A    decoder_output = BasicConstructor.subst(iop)
3062068SN/A    exec_output = FPFixedRoundingExecute.subst(iop)
3072068SN/A}};
3082068SN/A
309