fp.isa revision 4172:141705d83494
12086SN/A// -*- mode:c++ -*-
22086SN/A
32086SN/A// Copyright (c) 2003-2005 The Regents of The University of Michigan
42086SN/A// All rights reserved.
52086SN/A//
62086SN/A// Redistribution and use in source and binary forms, with or without
72086SN/A// modification, are permitted provided that the following conditions are
82086SN/A// met: redistributions of source code must retain the above copyright
92086SN/A// notice, this list of conditions and the following disclaimer;
102086SN/A// redistributions in binary form must reproduce the above copyright
112086SN/A// notice, this list of conditions and the following disclaimer in the
122086SN/A// documentation and/or other materials provided with the distribution;
132086SN/A// neither the name of the copyright holders nor the names of its
142086SN/A// contributors may be used to endorse or promote products derived from
152086SN/A// this software without specific prior written permission.
162086SN/A//
172086SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182086SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192086SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202086SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212086SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222086SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232086SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242086SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252086SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262086SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272086SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu//
292665Ssaidi@eecs.umich.edu// Authors: Steve Reinhardt
302665Ssaidi@eecs.umich.edu
312086SN/A////////////////////////////////////////////////////////////////////
322086SN/A//
332086SN/A// Floating-point instructions
342086SN/A//
352086SN/A//	Note that many FP-type instructions which do not support all the
362086SN/A//	various rounding & trapping modes use the simpler format
372086SN/A//	BasicOperateWithNopCheck.
382086SN/A//
392086SN/A
402086SN/Aoutput exec {{
412086SN/A    /// Check "FP enabled" machine status bit.  Called when executing any FP
422086SN/A    /// instruction in full-system mode.
432086SN/A    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
442086SN/A    /// if not.  Non-full-system mode: always returns NoFault.
452086SN/A#if FULL_SYSTEM
462152SN/A    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
472152SN/A    {
482152SN/A        Fault fault = NoFault;	// dummy... this ipr access should not fault
492086SN/A        if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) {
502086SN/A            fault = new FloatEnableFault;
512086SN/A        }
522152SN/A        return fault;
532652Ssaidi@eecs.umich.edu    }
542650Ssaidi@eecs.umich.edu#else
552086SN/A    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
562086SN/A    {
572086SN/A        return NoFault;
582152SN/A    }
592579SN/A#endif
602458SN/A}};
612600SN/A
622600SN/Aoutput header {{
632209SN/A    /**
642086SN/A     * Base class for general floating-point instructions.  Includes
652086SN/A     * support for various Alpha rounding and trapping modes.  Only FP
662152SN/A     * instructions that require this support are derived from this
672086SN/A     * class; the rest derive directly from AlphaStaticInst.
682086SN/A     */
692152SN/A    class AlphaFP : public AlphaStaticInst
702086SN/A    {
712152SN/A      public:
722086SN/A        /// Alpha FP rounding modes.
732152SN/A        enum RoundingMode {
742152SN/A            Chopped = 0,	///< round toward zero
752152SN/A            Minus_Infinity = 1, ///< round toward minus infinity
762152SN/A            Normal = 2,		///< round to nearest (default)
772152SN/A            Dynamic = 3,	///< use FPCR setting (in instruction)
782152SN/A            Plus_Infinity = 3	///< round to plus inifinity (in FPCR)
792152SN/A        };
802152SN/A
812152SN/A        /// Alpha FP trapping modes.
822086SN/A        /// For instructions that produce integer results, the
832086SN/A        /// "Underflow Enable" modes really mean "Overflow Enable", and
84        /// the assembly modifier is V rather than U.
85        enum TrappingMode {
86            /// default: nothing enabled
87            Imprecise = 0,		   ///< no modifier
88            /// underflow/overflow traps enabled, inexact disabled
89            Underflow_Imprecise = 1,	   ///< /U or /V
90            Underflow_Precise = 5,	   ///< /SU or /SV
91            /// underflow/overflow and inexact traps enabled
92            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
93        };
94
95      protected:
96        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
97        static const int alphaToC99RoundingMode[];
98
99        /// Map enum RoundingMode values to disassembly suffixes.
100        static const char *roundingModeSuffix[];
101        /// Map enum TrappingMode values to FP disassembly suffixes.
102        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        FE_TOWARDZERO,	// Chopped
196        FE_DOWNWARD,	// Minus_Infinity
197        FE_TONEAREST,	// Normal
198        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            fesetround(getC99RoundingMode(
232                           xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR)));
233            %(code)s;
234            fesetround(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