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