fp.isa revision 2649
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.
282068SN/A
292649Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////
302649Ssaidi@eecs.umich.edu//
312649Ssaidi@eecs.umich.edu// Floating-point instructions
322649Ssaidi@eecs.umich.edu//
332649Ssaidi@eecs.umich.edu//	Note that many FP-type instructions which do not support all the
342649Ssaidi@eecs.umich.edu//	various rounding & trapping modes use the simpler format
352649Ssaidi@eecs.umich.edu//	BasicOperateWithNopCheck.
362649Ssaidi@eecs.umich.edu//
372649Ssaidi@eecs.umich.edu
382068SN/Aoutput exec {{
392068SN/A    /// Check "FP enabled" machine status bit.  Called when executing any FP
402068SN/A    /// instruction in full-system mode.
412090SN/A    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
422090SN/A    /// if not.  Non-full-system mode: always returns NoFault.
432068SN/A#if FULL_SYSTEM
442132SN/A    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
452068SN/A    {
462132SN/A        Fault fault = NoFault;	// dummy... this ipr access should not fault
472159SN/A        if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
482147SN/A            fault = new FloatEnableFault;
492068SN/A        }
502068SN/A        return fault;
512068SN/A    }
522068SN/A#else
532132SN/A    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
542068SN/A    {
552090SN/A        return NoFault;
562068SN/A    }
572068SN/A#endif
582068SN/A}};
592068SN/A
602068SN/Aoutput header {{
612068SN/A    /**
622068SN/A     * Base class for general floating-point instructions.  Includes
632068SN/A     * support for various Alpha rounding and trapping modes.  Only FP
642068SN/A     * instructions that require this support are derived from this
652068SN/A     * class; the rest derive directly from AlphaStaticInst.
662068SN/A     */
672068SN/A    class AlphaFP : public AlphaStaticInst
682068SN/A    {
692068SN/A      public:
702068SN/A        /// Alpha FP rounding modes.
712068SN/A        enum RoundingMode {
722068SN/A            Chopped = 0,	///< round toward zero
732068SN/A            Minus_Infinity = 1, ///< round toward minus infinity
742068SN/A            Normal = 2,		///< round to nearest (default)
752068SN/A            Dynamic = 3,	///< use FPCR setting (in instruction)
762068SN/A            Plus_Infinity = 3	///< round to plus inifinity (in FPCR)
772068SN/A        };
782068SN/A
792068SN/A        /// Alpha FP trapping modes.
802068SN/A        /// For instructions that produce integer results, the
812068SN/A        /// "Underflow Enable" modes really mean "Overflow Enable", and
822068SN/A        /// the assembly modifier is V rather than U.
832068SN/A        enum TrappingMode {
842068SN/A            /// default: nothing enabled
852068SN/A            Imprecise = 0,		   ///< no modifier
862068SN/A            /// underflow/overflow traps enabled, inexact disabled
872068SN/A            Underflow_Imprecise = 1,	   ///< /U or /V
882068SN/A            Underflow_Precise = 5,	   ///< /SU or /SV
892068SN/A            /// underflow/overflow and inexact traps enabled
902068SN/A            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
912068SN/A        };
922068SN/A
932068SN/A      protected:
942068SN/A        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
952068SN/A        static const int alphaToC99RoundingMode[];
962068SN/A
972068SN/A        /// Map enum RoundingMode values to disassembly suffixes.
982068SN/A        static const char *roundingModeSuffix[];
992068SN/A        /// Map enum TrappingMode values to FP disassembly suffixes.
1002068SN/A        static const char *fpTrappingModeSuffix[];
1012068SN/A        /// Map enum TrappingMode values to integer disassembly suffixes.
1022068SN/A        static const char *intTrappingModeSuffix[];
1032068SN/A
1042068SN/A        /// This instruction's rounding mode.
1052068SN/A        RoundingMode roundingMode;
1062068SN/A        /// This instruction's trapping mode.
1072068SN/A        TrappingMode trappingMode;
1082068SN/A
1092068SN/A        /// Have we warned about this instruction's unsupported
1102068SN/A        /// rounding mode (if applicable)?
1112068SN/A        mutable bool warnedOnRounding;
1122068SN/A
1132068SN/A        /// Have we warned about this instruction's unsupported
1142068SN/A        /// trapping mode (if applicable)?
1152068SN/A        mutable bool warnedOnTrapping;
1162068SN/A
1172068SN/A        /// Constructor
1182227SN/A        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1192068SN/A            : AlphaStaticInst(mnem, _machInst, __opClass),
1202068SN/A              roundingMode((enum RoundingMode)FP_ROUNDMODE),
1212068SN/A              trappingMode((enum TrappingMode)FP_TRAPMODE),
1222068SN/A              warnedOnRounding(false),
1232068SN/A              warnedOnTrapping(false)
1242068SN/A        {
1252068SN/A        }
1262068SN/A
1272068SN/A        int getC99RoundingMode(uint64_t fpcr_val) const;
1282068SN/A
1292068SN/A        // This differs from the AlphaStaticInst version only in
1302068SN/A        // printing suffixes for non-default rounding & trapping modes.
1312068SN/A        std::string
1322068SN/A        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1332068SN/A    };
1342068SN/A
1352068SN/A}};
1362068SN/A
1372068SN/A
1382068SN/Aoutput decoder {{
1392068SN/A    int
1402068SN/A    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
1412068SN/A    {
1422068SN/A        if (roundingMode == Dynamic) {
1432068SN/A            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
1442068SN/A        }
1452068SN/A        else {
1462068SN/A            return alphaToC99RoundingMode[roundingMode];
1472068SN/A        }
1482068SN/A    }
1492068SN/A
1502068SN/A    std::string
1512068SN/A    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
1522068SN/A    {
1532068SN/A        std::string mnem_str(mnemonic);
1542068SN/A
1552068SN/A#ifndef SS_COMPATIBLE_DISASSEMBLY
1562068SN/A        std::string suffix("");
1572068SN/A        suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
1582068SN/A                   ? fpTrappingModeSuffix[trappingMode]
1592068SN/A                   : intTrappingModeSuffix[trappingMode]);
1602068SN/A        suffix += roundingModeSuffix[roundingMode];
1612068SN/A
1622068SN/A        if (suffix != "") {
1632068SN/A            mnem_str = csprintf("%s/%s", mnemonic, suffix);
1642068SN/A        }
1652068SN/A#endif
1662068SN/A
1672068SN/A        std::stringstream ss;
1682068SN/A        ccprintf(ss, "%-10s ", mnem_str.c_str());
1692068SN/A
1702068SN/A        // just print the first two source regs... if there's
1712068SN/A        // a third one, it's a read-modify-write dest (Rc),
1722068SN/A        // e.g. for CMOVxx
1732068SN/A        if (_numSrcRegs > 0) {
1742068SN/A            printReg(ss, _srcRegIdx[0]);
1752068SN/A        }
1762068SN/A        if (_numSrcRegs > 1) {
1772068SN/A            ss << ",";
1782068SN/A            printReg(ss, _srcRegIdx[1]);
1792068SN/A        }
1802068SN/A
1812068SN/A        // just print the first dest... if there's a second one,
1822068SN/A        // it's generally implicit
1832068SN/A        if (_numDestRegs > 0) {
1842068SN/A            if (_numSrcRegs > 0)
1852068SN/A                ss << ",";
1862068SN/A            printReg(ss, _destRegIdx[0]);
1872068SN/A        }
1882068SN/A
1892068SN/A        return ss.str();
1902068SN/A    }
1912068SN/A
1922068SN/A    const int AlphaFP::alphaToC99RoundingMode[] = {
1932068SN/A        FE_TOWARDZERO,	// Chopped
1942068SN/A        FE_DOWNWARD,	// Minus_Infinity
1952068SN/A        FE_TONEAREST,	// Normal
1962068SN/A        FE_UPWARD	// Dynamic in inst, Plus_Infinity in FPCR
1972068SN/A    };
1982068SN/A
1992068SN/A    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
2002068SN/A    // mark invalid trapping modes, but don't fail on them, because
2012068SN/A    // you could decode anything on a misspeculated path
2022068SN/A    const char *AlphaFP::fpTrappingModeSuffix[] =
2032068SN/A        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
2042068SN/A    const char *AlphaFP::intTrappingModeSuffix[] =
2052068SN/A        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
2062068SN/A}};
2072068SN/A
2082068SN/A// FP instruction class execute method template.  Handles non-standard
2092068SN/A// rounding modes.
2102068SN/Adef template FloatingPointExecute {{
2112132SN/A    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
2122068SN/A                                  Trace::InstRecord *traceData) const
2132068SN/A    {
2142068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2152068SN/A            warn("%s: non-standard trapping mode not supported",
2162068SN/A                 generateDisassembly(0, NULL));
2172068SN/A            warnedOnTrapping = true;
2182068SN/A        }
2192068SN/A
2202132SN/A        Fault fault = NoFault;
2212068SN/A
2222068SN/A        %(fp_enable_check)s;
2232068SN/A        %(op_decl)s;
2242068SN/A        %(op_rd)s;
2252068SN/A#if USE_FENV
2262068SN/A        if (roundingMode == Normal) {
2272068SN/A            %(code)s;
2282068SN/A        } else {
2292159SN/A            fesetround(getC99RoundingMode(
2302159SN/A                           xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
2312068SN/A            %(code)s;
2322068SN/A            fesetround(FE_TONEAREST);
2332068SN/A        }
2342068SN/A#else
2352068SN/A        if (roundingMode != Normal && !warnedOnRounding) {
2362068SN/A            warn("%s: non-standard rounding mode not supported",
2372068SN/A                 generateDisassembly(0, NULL));
2382068SN/A            warnedOnRounding = true;
2392068SN/A        }
2402068SN/A        %(code)s;
2412068SN/A#endif
2422068SN/A
2432090SN/A        if (fault == NoFault) {
2442068SN/A            %(op_wb)s;
2452068SN/A        }
2462068SN/A
2472068SN/A        return fault;
2482068SN/A    }
2492068SN/A}};
2502068SN/A
2512068SN/A// FP instruction class execute method template where no dynamic
2522068SN/A// rounding mode control is needed.  Like BasicExecute, but includes
2532068SN/A// check & warning for non-standard trapping mode.
2542068SN/Adef template FPFixedRoundingExecute {{
2552132SN/A    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
2562068SN/A                                  Trace::InstRecord *traceData) const
2572068SN/A    {
2582068SN/A        if (trappingMode != Imprecise && !warnedOnTrapping) {
2592068SN/A            warn("%s: non-standard trapping mode not supported",
2602068SN/A                 generateDisassembly(0, NULL));
2612068SN/A            warnedOnTrapping = true;
2622068SN/A        }
2632068SN/A
2642132SN/A        Fault fault = NoFault;
2652068SN/A
2662068SN/A        %(fp_enable_check)s;
2672068SN/A        %(op_decl)s;
2682068SN/A        %(op_rd)s;
2692068SN/A        %(code)s;
2702068SN/A
2712090SN/A        if (fault == NoFault) {
2722068SN/A            %(op_wb)s;
2732068SN/A        }
2742068SN/A
2752068SN/A        return fault;
2762068SN/A    }
2772068SN/A}};
2782068SN/A
2792068SN/Adef template FloatingPointDecode {{
2802068SN/A {
2812068SN/A     AlphaStaticInst *i = new %(class_name)s(machInst);
2822068SN/A     if (FC == 31) {
2832068SN/A         i = makeNop(i);
2842068SN/A     }
2852068SN/A     return i;
2862068SN/A }
2872068SN/A}};
2882068SN/A
2892068SN/A// General format for floating-point operate instructions:
2902068SN/A// - Checks trapping and rounding mode flags.  Trapping modes
2912068SN/A//   currently unimplemented (will fail).
2922068SN/A// - Generates NOP if FC == 31.
2932068SN/Adef format FloatingPointOperate(code, *opt_args) {{
2942068SN/A    iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
2952068SN/A    decode_block = FloatingPointDecode.subst(iop)
2962068SN/A    header_output = BasicDeclare.subst(iop)
2972068SN/A    decoder_output = BasicConstructor.subst(iop)
2982068SN/A    exec_output = FloatingPointExecute.subst(iop)
2992068SN/A}};
3002068SN/A
3012068SN/A// Special format for cvttq where rounding mode is pre-decoded
3022068SN/Adef format FPFixedRounding(code, class_suffix, *opt_args) {{
3032068SN/A    Name += class_suffix
3042068SN/A    iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
3052068SN/A    decode_block = FloatingPointDecode.subst(iop)
3062068SN/A    header_output = BasicDeclare.subst(iop)
3072068SN/A    decoder_output = BasicConstructor.subst(iop)
3082068SN/A    exec_output = FPFixedRoundingExecute.subst(iop)
3092068SN/A}};
3102068SN/A
311