fp.isa revision 12106
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.
4510196SCurtis.Dunham@arm.com    inline Fault checkFpEnableFault(CPU_EXEC_CONTEXT *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    }
532068SN/A}};
542068SN/A
552068SN/Aoutput header {{
562068SN/A    /**
572068SN/A     * Base class for general floating-point instructions.  Includes
582068SN/A     * support for various Alpha rounding and trapping modes.  Only FP
592068SN/A     * instructions that require this support are derived from this
602068SN/A     * class; the rest derive directly from AlphaStaticInst.
612068SN/A     */
622068SN/A    class AlphaFP : public AlphaStaticInst
632068SN/A    {
642068SN/A      public:
652068SN/A        /// Alpha FP rounding modes.
662068SN/A        enum RoundingMode {
677799Sgblack@eecs.umich.edu            Chopped = 0,        ///< round toward zero
682068SN/A            Minus_Infinity = 1, ///< round toward minus infinity
697799Sgblack@eecs.umich.edu            Normal = 2,         ///< round to nearest (default)
707799Sgblack@eecs.umich.edu            Dynamic = 3,        ///< use FPCR setting (in instruction)
717799Sgblack@eecs.umich.edu            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
722068SN/A        };
732068SN/A
742068SN/A        /// Alpha FP trapping modes.
752068SN/A        /// For instructions that produce integer results, the
762068SN/A        /// "Underflow Enable" modes really mean "Overflow Enable", and
772068SN/A        /// the assembly modifier is V rather than U.
782068SN/A        enum TrappingMode {
792068SN/A            /// default: nothing enabled
807799Sgblack@eecs.umich.edu            Imprecise = 0,                 ///< no modifier
812068SN/A            /// underflow/overflow traps enabled, inexact disabled
827799Sgblack@eecs.umich.edu            Underflow_Imprecise = 1,       ///< /U or /V
837799Sgblack@eecs.umich.edu            Underflow_Precise = 5,         ///< /SU or /SV
842068SN/A            /// underflow/overflow and inexact traps enabled
852068SN/A            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
862068SN/A        };
872068SN/A
882068SN/A      protected:
892068SN/A        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
902068SN/A        static const int alphaToC99RoundingMode[];
912068SN/A
922068SN/A        /// Map enum RoundingMode values to disassembly suffixes.
932068SN/A        static const char *roundingModeSuffix[];
942068SN/A        /// Map enum TrappingMode values to FP disassembly suffixes.
952068SN/A        static const char *fpTrappingModeSuffix[];
962068SN/A        /// Map enum TrappingMode values to integer disassembly suffixes.
972068SN/A        static const char *intTrappingModeSuffix[];
982068SN/A
992068SN/A        /// This instruction's rounding mode.
1002068SN/A        RoundingMode roundingMode;
1012068SN/A        /// This instruction's trapping mode.
1022068SN/A        TrappingMode trappingMode;
1032068SN/A
1042068SN/A        /// Have we warned about this instruction's unsupported
1052068SN/A        /// rounding mode (if applicable)?
1062068SN/A        mutable bool warnedOnRounding;
1072068SN/A
1082068SN/A        /// Have we warned about this instruction's unsupported
1092068SN/A        /// trapping mode (if applicable)?
1102068SN/A        mutable bool warnedOnTrapping;
1112068SN/A
1122068SN/A        /// Constructor
1132227SN/A        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1142068SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
1152068SN/A              roundingMode((enum RoundingMode)FP_ROUNDMODE),
1162068SN/A              trappingMode((enum TrappingMode)FP_TRAPMODE),
1172068SN/A              warnedOnRounding(false),
1182068SN/A              warnedOnTrapping(false)
1192068SN/A        {
1202068SN/A        }
1212068SN/A
1222068SN/A        int getC99RoundingMode(uint64_t fpcr_val) const;
1232068SN/A
1242068SN/A        // This differs from the AlphaStaticInst version only in
1252068SN/A        // printing suffixes for non-default rounding & trapping modes.
1262068SN/A        std::string
1272068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1282068SN/A    };
1292068SN/A
1302068SN/A}};
1312068SN/A
1322068SN/A
1332068SN/Aoutput decoder {{
1342068SN/A    int
1352068SN/A    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
1362068SN/A    {
1372068SN/A        if (roundingMode == Dynamic) {
1382068SN/A            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
1392068SN/A        }
1402068SN/A        else {
1412068SN/A            return alphaToC99RoundingMode[roundingMode];
1422068SN/A        }
1432068SN/A    }
1442068SN/A
1452068SN/A    std::string
1462068SN/A    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1472068SN/A    {
1482068SN/A        std::string mnem_str(mnemonic);
1492068SN/A
1502068SN/A#ifndef SS_COMPATIBLE_DISASSEMBLY
1512068SN/A        std::string suffix("");
15212106SRekai.GonzalezAlberquilla@arm.com        suffix += ((_destRegIdx[0].isFloatReg())
1532068SN/A                   ? fpTrappingModeSuffix[trappingMode]
1542068SN/A                   : intTrappingModeSuffix[trappingMode]);
1552068SN/A        suffix += roundingModeSuffix[roundingMode];
1562068SN/A
1572068SN/A        if (suffix != "") {
1582068SN/A            mnem_str = csprintf("%s/%s", mnemonic, suffix);
1592068SN/A        }
1602068SN/A#endif
1612068SN/A
1622068SN/A        std::stringstream ss;
1632068SN/A        ccprintf(ss, "%-10s ", mnem_str.c_str());
1642068SN/A
1652068SN/A        // just print the first two source regs... if there's
1662068SN/A        // a third one, it's a read-modify-write dest (Rc),
1672068SN/A        // e.g. for CMOVxx
1682068SN/A        if (_numSrcRegs > 0) {
1692068SN/A            printReg(ss, _srcRegIdx[0]);
1702068SN/A        }
1712068SN/A        if (_numSrcRegs > 1) {
1722068SN/A            ss << ",";
1732068SN/A            printReg(ss, _srcRegIdx[1]);
1742068SN/A        }
1752068SN/A
1762068SN/A        // just print the first dest... if there's a second one,
1772068SN/A        // it's generally implicit
1782068SN/A        if (_numDestRegs > 0) {
1792068SN/A            if (_numSrcRegs > 0)
1802068SN/A                ss << ",";
1812068SN/A            printReg(ss, _destRegIdx[0]);
1822068SN/A        }
1832068SN/A
1842068SN/A        return ss.str();
1852068SN/A    }
1862068SN/A
1872068SN/A    const int AlphaFP::alphaToC99RoundingMode[] = {
1887799Sgblack@eecs.umich.edu        M5_FE_TOWARDZERO,       // Chopped
1897799Sgblack@eecs.umich.edu        M5_FE_DOWNWARD, // Minus_Infinity
1907799Sgblack@eecs.umich.edu        M5_FE_TONEAREST,        // Normal
1917799Sgblack@eecs.umich.edu        M5_FE_UPWARD    // Dynamic in inst, Plus_Infinity in FPCR
1922068SN/A    };
1932068SN/A
1942068SN/A    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
1952068SN/A    // mark invalid trapping modes, but don't fail on them, because
1962068SN/A    // you could decode anything on a misspeculated path
1972068SN/A    const char *AlphaFP::fpTrappingModeSuffix[] =
1982068SN/A        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
1992068SN/A    const char *AlphaFP::intTrappingModeSuffix[] =
2002068SN/A        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
2012068SN/A}};
2022068SN/A
2032068SN/A// FP instruction class execute method template.  Handles non-standard
2042068SN/A// rounding modes.
2052068SN/Adef template FloatingPointExecute {{
20610196SCurtis.Dunham@arm.com    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
2072068SN/A                                  Trace::InstRecord *traceData) const
2082068SN/A    {
2092068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2102068SN/A            warn("%s: non-standard trapping mode not supported",
2112068SN/A                 generateDisassembly(0, NULL));
2122068SN/A            warnedOnTrapping = true;
2132068SN/A        }
2142068SN/A
2152132SN/A        Fault fault = NoFault;
2162068SN/A
2172068SN/A        %(fp_enable_check)s;
2182068SN/A        %(op_decl)s;
2192068SN/A        %(op_rd)s;
2202068SN/A#if USE_FENV
2212068SN/A        if (roundingMode == Normal) {
2222068SN/A            %(code)s;
2232068SN/A        } else {
2244394Ssaidi@eecs.umich.edu            m5_fesetround(getC99RoundingMode(
2257783SGiacomo.Gabrielli@arm.com                           xc->readMiscReg(MISCREG_FPCR)));
2262068SN/A            %(code)s;
2274394Ssaidi@eecs.umich.edu            m5_fesetround(M5_FE_TONEAREST);
2282068SN/A        }
2292068SN/A#else
2302068SN/A        if (roundingMode != Normal && !warnedOnRounding) {
2312068SN/A            warn("%s: non-standard rounding mode not supported",
2322068SN/A                 generateDisassembly(0, NULL));
2332068SN/A            warnedOnRounding = true;
2342068SN/A        }
2352068SN/A        %(code)s;
2362068SN/A#endif
2372068SN/A
2382090SN/A        if (fault == NoFault) {
2392068SN/A            %(op_wb)s;
2402068SN/A        }
2412068SN/A
2422068SN/A        return fault;
2432068SN/A    }
2442068SN/A}};
2452068SN/A
2462068SN/A// FP instruction class execute method template where no dynamic
2472068SN/A// rounding mode control is needed.  Like BasicExecute, but includes
2482068SN/A// check & warning for non-standard trapping mode.
2492068SN/Adef template FPFixedRoundingExecute {{
25010196SCurtis.Dunham@arm.com    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
2512068SN/A                                  Trace::InstRecord *traceData) const
2522068SN/A    {
2532068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2542068SN/A            warn("%s: non-standard trapping mode not supported",
2552068SN/A                 generateDisassembly(0, NULL));
2562068SN/A            warnedOnTrapping = true;
2572068SN/A        }
2582068SN/A
2592132SN/A        Fault fault = NoFault;
2602068SN/A
2612068SN/A        %(fp_enable_check)s;
2622068SN/A        %(op_decl)s;
2632068SN/A        %(op_rd)s;
2642068SN/A        %(code)s;
2652068SN/A
2662090SN/A        if (fault == NoFault) {
2672068SN/A            %(op_wb)s;
2682068SN/A        }
2692068SN/A
2702068SN/A        return fault;
2712068SN/A    }
2722068SN/A}};
2732068SN/A
2742068SN/Adef template FloatingPointDecode {{
2752068SN/A {
2762068SN/A     AlphaStaticInst *i = new %(class_name)s(machInst);
2772068SN/A     if (FC == 31) {
2782068SN/A         i = makeNop(i);
2792068SN/A     }
2802068SN/A     return i;
2812068SN/A }
2822068SN/A}};
2832068SN/A
2842068SN/A// General format for floating-point operate instructions:
2852068SN/A// - Checks trapping and rounding mode flags.  Trapping modes
2862068SN/A//   currently unimplemented (will fail).
2872068SN/A// - Generates NOP if FC == 31.
2882068SN/Adef format FloatingPointOperate(code, *opt_args) {{
2893953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
2902068SN/A    decode_block = FloatingPointDecode.subst(iop)
2912068SN/A    header_output = BasicDeclare.subst(iop)
2922068SN/A    decoder_output = BasicConstructor.subst(iop)
2932068SN/A    exec_output = FloatingPointExecute.subst(iop)
2942068SN/A}};
2952068SN/A
2962068SN/A// Special format for cvttq where rounding mode is pre-decoded
2972068SN/Adef format FPFixedRounding(code, class_suffix, *opt_args) {{
2982068SN/A    Name += class_suffix
2993953Sstever@eecs.umich.edu    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
3002068SN/A    decode_block = FloatingPointDecode.subst(iop)
3012068SN/A    header_output = BasicDeclare.subst(iop)
3022068SN/A    decoder_output = BasicConstructor.subst(iop)
3032068SN/A    exec_output = FPFixedRoundingExecute.subst(iop)
3042068SN/A}};
3052068SN/A
306