fp.isa revision 7799
111986Sandreas.sandberg@arm.com// -*- mode:c++ -*-
211986Sandreas.sandberg@arm.com
311986Sandreas.sandberg@arm.com// Copyright (c) 2003-2005 The Regents of The University of Michigan
411986Sandreas.sandberg@arm.com// All rights reserved.
511986Sandreas.sandberg@arm.com//
611986Sandreas.sandberg@arm.com// Redistribution and use in source and binary forms, with or without
711986Sandreas.sandberg@arm.com// modification, are permitted provided that the following conditions are
811986Sandreas.sandberg@arm.com// met: redistributions of source code must retain the above copyright
911986Sandreas.sandberg@arm.com// notice, this list of conditions and the following disclaimer;
1011986Sandreas.sandberg@arm.com// redistributions in binary form must reproduce the above copyright
1114299Sbbruce@ucdavis.edu// notice, this list of conditions and the following disclaimer in the
1211986Sandreas.sandberg@arm.com// documentation and/or other materials provided with the distribution;
1311986Sandreas.sandberg@arm.com// neither the name of the copyright holders nor the names of its
1412391Sjason@lowepower.com// contributors may be used to endorse or promote products derived from
1512391Sjason@lowepower.com// this software without specific prior written permission.
1611986Sandreas.sandberg@arm.com//
1712391Sjason@lowepower.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1812391Sjason@lowepower.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1912391Sjason@lowepower.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2012391Sjason@lowepower.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2111986Sandreas.sandberg@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2211986Sandreas.sandberg@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2311986Sandreas.sandberg@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2412391Sjason@lowepower.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2512391Sjason@lowepower.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2612391Sjason@lowepower.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2712391Sjason@lowepower.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2812391Sjason@lowepower.com//
2912391Sjason@lowepower.com// Authors: Steve Reinhardt
3012391Sjason@lowepower.com
3112391Sjason@lowepower.com////////////////////////////////////////////////////////////////////
3211986Sandreas.sandberg@arm.com//
3312391Sjason@lowepower.com// Floating-point instructions
3412391Sjason@lowepower.com//
3511986Sandreas.sandberg@arm.com//      Note that many FP-type instructions which do not support all the
3612391Sjason@lowepower.com//      various rounding & trapping modes use the simpler format
3714299Sbbruce@ucdavis.edu//      BasicOperateWithNopCheck.
3814299Sbbruce@ucdavis.edu//
3914299Sbbruce@ucdavis.edu
4012391Sjason@lowepower.comoutput exec {{
4112391Sjason@lowepower.com    /// Check "FP enabled" machine status bit.  Called when executing any FP
4212391Sjason@lowepower.com    /// instruction in full-system mode.
4311986Sandreas.sandberg@arm.com    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
4412391Sjason@lowepower.com    /// if not.  Non-full-system mode: always returns NoFault.
4512391Sjason@lowepower.com#if FULL_SYSTEM
4612391Sjason@lowepower.com    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
4712391Sjason@lowepower.com    {
4812391Sjason@lowepower.com        Fault fault = NoFault;  // dummy... this ipr access should not fault
4912391Sjason@lowepower.com        if (!ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
5012391Sjason@lowepower.com            fault = new FloatEnableFault;
5112391Sjason@lowepower.com        }
5212391Sjason@lowepower.com        return fault;
5312391Sjason@lowepower.com    }
5412391Sjason@lowepower.com#else
5512391Sjason@lowepower.com    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
5612391Sjason@lowepower.com    {
5712391Sjason@lowepower.com        return NoFault;
5812391Sjason@lowepower.com    }
5914299Sbbruce@ucdavis.edu#endif
6014299Sbbruce@ucdavis.edu}};
6114299Sbbruce@ucdavis.edu
6214299Sbbruce@ucdavis.eduoutput header {{
6314299Sbbruce@ucdavis.edu    /**
6414299Sbbruce@ucdavis.edu     * Base class for general floating-point instructions.  Includes
6514299Sbbruce@ucdavis.edu     * support for various Alpha rounding and trapping modes.  Only FP
6614299Sbbruce@ucdavis.edu     * instructions that require this support are derived from this
6714299Sbbruce@ucdavis.edu     * class; the rest derive directly from AlphaStaticInst.
6814299Sbbruce@ucdavis.edu     */
6914299Sbbruce@ucdavis.edu    class AlphaFP : public AlphaStaticInst
7014299Sbbruce@ucdavis.edu    {
7114299Sbbruce@ucdavis.edu      public:
7214299Sbbruce@ucdavis.edu        /// Alpha FP rounding modes.
7314299Sbbruce@ucdavis.edu        enum RoundingMode {
7414299Sbbruce@ucdavis.edu            Chopped = 0,        ///< round toward zero
7514299Sbbruce@ucdavis.edu            Minus_Infinity = 1, ///< round toward minus infinity
7614299Sbbruce@ucdavis.edu            Normal = 2,         ///< round to nearest (default)
7714299Sbbruce@ucdavis.edu            Dynamic = 3,        ///< use FPCR setting (in instruction)
7814299Sbbruce@ucdavis.edu            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
7914299Sbbruce@ucdavis.edu        };
8014299Sbbruce@ucdavis.edu
8114299Sbbruce@ucdavis.edu        /// Alpha FP trapping modes.
8214299Sbbruce@ucdavis.edu        /// For instructions that produce integer results, the
8314299Sbbruce@ucdavis.edu        /// "Underflow Enable" modes really mean "Overflow Enable", and
8414299Sbbruce@ucdavis.edu        /// the assembly modifier is V rather than U.
8514299Sbbruce@ucdavis.edu        enum TrappingMode {
8614299Sbbruce@ucdavis.edu            /// default: nothing enabled
8712391Sjason@lowepower.com            Imprecise = 0,                 ///< no modifier
8812391Sjason@lowepower.com            /// underflow/overflow traps enabled, inexact disabled
8912391Sjason@lowepower.com            Underflow_Imprecise = 1,       ///< /U or /V
9012391Sjason@lowepower.com            Underflow_Precise = 5,         ///< /SU or /SV
9112391Sjason@lowepower.com            /// underflow/overflow and inexact traps enabled
9212391Sjason@lowepower.com            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
9312391Sjason@lowepower.com        };
9412391Sjason@lowepower.com
9512391Sjason@lowepower.com      protected:
9612391Sjason@lowepower.com        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
9712391Sjason@lowepower.com        static const int alphaToC99RoundingMode[];
9812391Sjason@lowepower.com
9911986Sandreas.sandberg@arm.com        /// Map enum RoundingMode values to disassembly suffixes.
10011986Sandreas.sandberg@arm.com        static const char *roundingModeSuffix[];
10111986Sandreas.sandberg@arm.com        /// Map enum TrappingMode values to FP disassembly suffixes.
10212391Sjason@lowepower.com        static const char *fpTrappingModeSuffix[];
103        /// Map enum TrappingMode values to integer disassembly suffixes.
104        static const char *intTrappingModeSuffix[];
105
106        /// This instruction's rounding mode.
107        RoundingMode roundingMode;
108        /// This instruction's trapping mode.
109        TrappingMode trappingMode;
110
111        /// Have we warned about this instruction's unsupported
112        /// rounding mode (if applicable)?
113        mutable bool warnedOnRounding;
114
115        /// Have we warned about this instruction's unsupported
116        /// trapping mode (if applicable)?
117        mutable bool warnedOnTrapping;
118
119        /// Constructor
120        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
121            : AlphaStaticInst(mnem, _machInst, __opClass),
122              roundingMode((enum RoundingMode)FP_ROUNDMODE),
123              trappingMode((enum TrappingMode)FP_TRAPMODE),
124              warnedOnRounding(false),
125              warnedOnTrapping(false)
126        {
127        }
128
129        int getC99RoundingMode(uint64_t fpcr_val) const;
130
131        // This differs from the AlphaStaticInst version only in
132        // printing suffixes for non-default rounding & trapping modes.
133        std::string
134        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
135    };
136
137}};
138
139
140output decoder {{
141    int
142    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
143    {
144        if (roundingMode == Dynamic) {
145            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
146        }
147        else {
148            return alphaToC99RoundingMode[roundingMode];
149        }
150    }
151
152    std::string
153    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
154    {
155        std::string mnem_str(mnemonic);
156
157#ifndef SS_COMPATIBLE_DISASSEMBLY
158        std::string suffix("");
159        suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
160                   ? fpTrappingModeSuffix[trappingMode]
161                   : intTrappingModeSuffix[trappingMode]);
162        suffix += roundingModeSuffix[roundingMode];
163
164        if (suffix != "") {
165            mnem_str = csprintf("%s/%s", mnemonic, suffix);
166        }
167#endif
168
169        std::stringstream ss;
170        ccprintf(ss, "%-10s ", mnem_str.c_str());
171
172        // just print the first two source regs... if there's
173        // a third one, it's a read-modify-write dest (Rc),
174        // e.g. for CMOVxx
175        if (_numSrcRegs > 0) {
176            printReg(ss, _srcRegIdx[0]);
177        }
178        if (_numSrcRegs > 1) {
179            ss << ",";
180            printReg(ss, _srcRegIdx[1]);
181        }
182
183        // just print the first dest... if there's a second one,
184        // it's generally implicit
185        if (_numDestRegs > 0) {
186            if (_numSrcRegs > 0)
187                ss << ",";
188            printReg(ss, _destRegIdx[0]);
189        }
190
191        return ss.str();
192    }
193
194    const int AlphaFP::alphaToC99RoundingMode[] = {
195        M5_FE_TOWARDZERO,       // Chopped
196        M5_FE_DOWNWARD, // Minus_Infinity
197        M5_FE_TONEAREST,        // Normal
198        M5_FE_UPWARD    // Dynamic in inst, Plus_Infinity in FPCR
199    };
200
201    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
202    // mark invalid trapping modes, but don't fail on them, because
203    // you could decode anything on a misspeculated path
204    const char *AlphaFP::fpTrappingModeSuffix[] =
205        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
206    const char *AlphaFP::intTrappingModeSuffix[] =
207        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
208}};
209
210// FP instruction class execute method template.  Handles non-standard
211// rounding modes.
212def template FloatingPointExecute {{
213    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
214                                  Trace::InstRecord *traceData) const
215    {
216        if (trappingMode != Imprecise && !warnedOnTrapping) {
217            warn("%s: non-standard trapping mode not supported",
218                 generateDisassembly(0, NULL));
219            warnedOnTrapping = true;
220        }
221
222        Fault fault = NoFault;
223
224        %(fp_enable_check)s;
225        %(op_decl)s;
226        %(op_rd)s;
227#if USE_FENV
228        if (roundingMode == Normal) {
229            %(code)s;
230        } else {
231            m5_fesetround(getC99RoundingMode(
232                           xc->readMiscReg(MISCREG_FPCR)));
233            %(code)s;
234            m5_fesetround(M5_FE_TONEAREST);
235        }
236#else
237        if (roundingMode != Normal && !warnedOnRounding) {
238            warn("%s: non-standard rounding mode not supported",
239                 generateDisassembly(0, NULL));
240            warnedOnRounding = true;
241        }
242        %(code)s;
243#endif
244
245        if (fault == NoFault) {
246            %(op_wb)s;
247        }
248
249        return fault;
250    }
251}};
252
253// FP instruction class execute method template where no dynamic
254// rounding mode control is needed.  Like BasicExecute, but includes
255// check & warning for non-standard trapping mode.
256def template FPFixedRoundingExecute {{
257    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
258                                  Trace::InstRecord *traceData) const
259    {
260        if (trappingMode != Imprecise && !warnedOnTrapping) {
261            warn("%s: non-standard trapping mode not supported",
262                 generateDisassembly(0, NULL));
263            warnedOnTrapping = true;
264        }
265
266        Fault fault = NoFault;
267
268        %(fp_enable_check)s;
269        %(op_decl)s;
270        %(op_rd)s;
271        %(code)s;
272
273        if (fault == NoFault) {
274            %(op_wb)s;
275        }
276
277        return fault;
278    }
279}};
280
281def template FloatingPointDecode {{
282 {
283     AlphaStaticInst *i = new %(class_name)s(machInst);
284     if (FC == 31) {
285         i = makeNop(i);
286     }
287     return i;
288 }
289}};
290
291// General format for floating-point operate instructions:
292// - Checks trapping and rounding mode flags.  Trapping modes
293//   currently unimplemented (will fail).
294// - Generates NOP if FC == 31.
295def format FloatingPointOperate(code, *opt_args) {{
296    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
297    decode_block = FloatingPointDecode.subst(iop)
298    header_output = BasicDeclare.subst(iop)
299    decoder_output = BasicConstructor.subst(iop)
300    exec_output = FloatingPointExecute.subst(iop)
301}};
302
303// Special format for cvttq where rounding mode is pre-decoded
304def format FPFixedRounding(code, class_suffix, *opt_args) {{
305    Name += class_suffix
306    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
307    decode_block = FloatingPointDecode.subst(iop)
308    header_output = BasicDeclare.subst(iop)
309    decoder_output = BasicConstructor.subst(iop)
310    exec_output = FPFixedRoundingExecute.subst(iop)
311}};
312
313