fp.isa revision 10196:be0e1724eb39
12650Ssaidi@eecs.umich.edu// -*- mode:c++ -*-
22650Ssaidi@eecs.umich.edu
32650Ssaidi@eecs.umich.edu// Copyright (c) 2003-2005 The Regents of The University of Michigan
42650Ssaidi@eecs.umich.edu// All rights reserved.
52650Ssaidi@eecs.umich.edu//
62650Ssaidi@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
72650Ssaidi@eecs.umich.edu// modification, are permitted provided that the following conditions are
82650Ssaidi@eecs.umich.edu// met: redistributions of source code must retain the above copyright
92650Ssaidi@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
102650Ssaidi@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
112650Ssaidi@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
122650Ssaidi@eecs.umich.edu// documentation and/or other materials provided with the distribution;
132650Ssaidi@eecs.umich.edu// neither the name of the copyright holders nor the names of its
142650Ssaidi@eecs.umich.edu// contributors may be used to endorse or promote products derived from
152650Ssaidi@eecs.umich.edu// this software without specific prior written permission.
162650Ssaidi@eecs.umich.edu//
172650Ssaidi@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182650Ssaidi@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192650Ssaidi@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202650Ssaidi@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212650Ssaidi@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222650Ssaidi@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232650Ssaidi@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242650Ssaidi@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252650Ssaidi@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262650Ssaidi@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272665Ssaidi@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284070Ssaidi@eecs.umich.edu//
292650Ssaidi@eecs.umich.edu// Authors: Steve Reinhardt
302650Ssaidi@eecs.umich.edu
312650Ssaidi@eecs.umich.edu////////////////////////////////////////////////////////////////////
322650Ssaidi@eecs.umich.edu//
338229Snate@binkert.org// Floating-point instructions
343529Sgblack@eecs.umich.edu//
358229Snate@binkert.org//      Note that many FP-type instructions which do not support all the
364070Ssaidi@eecs.umich.edu//      various rounding & trapping modes use the simpler format
372650Ssaidi@eecs.umich.edu//      BasicOperateWithNopCheck.
382680Sktlim@umich.edu//
398232Snate@binkert.org
402650Ssaidi@eecs.umich.eduoutput exec {{
412650Ssaidi@eecs.umich.edu    /// Check "FP enabled" machine status bit.  Called when executing any FP
422650Ssaidi@eecs.umich.edu    /// instruction in full-system mode.
432650Ssaidi@eecs.umich.edu    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
445560Snate@binkert.org    /// if not.  Non-full-system mode: always returns NoFault.
455560Snate@binkert.org    inline Fault checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
465560Snate@binkert.org    {
475560Snate@binkert.org        Fault fault = NoFault;  // dummy... this ipr access should not fault
482650Ssaidi@eecs.umich.edu        if (FullSystem && !ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
495560Snate@binkert.org            fault = new FloatEnableFault;
505560Snate@binkert.org        }
515560Snate@binkert.org        return fault;
525560Snate@binkert.org    }
535560Snate@binkert.org}};
544070Ssaidi@eecs.umich.edu
555560Snate@binkert.orgoutput header {{
565560Snate@binkert.org    /**
575560Snate@binkert.org     * Base class for general floating-point instructions.  Includes
585560Snate@binkert.org     * support for various Alpha rounding and trapping modes.  Only FP
595560Snate@binkert.org     * instructions that require this support are derived from this
605560Snate@binkert.org     * class; the rest derive directly from AlphaStaticInst.
615560Snate@binkert.org     */
625560Snate@binkert.org    class AlphaFP : public AlphaStaticInst
635560Snate@binkert.org    {
645560Snate@binkert.org      public:
655560Snate@binkert.org        /// Alpha FP rounding modes.
665560Snate@binkert.org        enum RoundingMode {
675560Snate@binkert.org            Chopped = 0,        ///< round toward zero
685560Snate@binkert.org            Minus_Infinity = 1, ///< round toward minus infinity
695560Snate@binkert.org            Normal = 2,         ///< round to nearest (default)
705560Snate@binkert.org            Dynamic = 3,        ///< use FPCR setting (in instruction)
715560Snate@binkert.org            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
725560Snate@binkert.org        };
735560Snate@binkert.org
745560Snate@binkert.org        /// Alpha FP trapping modes.
757741Sgblack@eecs.umich.edu        /// For instructions that produce integer results, the
765560Snate@binkert.org        /// "Underflow Enable" modes really mean "Overflow Enable", and
775560Snate@binkert.org        /// the assembly modifier is V rather than U.
785560Snate@binkert.org        enum TrappingMode {
795560Snate@binkert.org            /// default: nothing enabled
805560Snate@binkert.org            Imprecise = 0,                 ///< no modifier
815560Snate@binkert.org            /// underflow/overflow traps enabled, inexact disabled
827741Sgblack@eecs.umich.edu            Underflow_Imprecise = 1,       ///< /U or /V
835560Snate@binkert.org            Underflow_Precise = 5,         ///< /SU or /SV
845560Snate@binkert.org            /// underflow/overflow and inexact traps enabled
856022Sgblack@eecs.umich.edu            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
866022Sgblack@eecs.umich.edu        };
875560Snate@binkert.org
885560Snate@binkert.org      protected:
895560Snate@binkert.org        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
905560Snate@binkert.org        static const int alphaToC99RoundingMode[];
915560Snate@binkert.org
925560Snate@binkert.org        /// Map enum RoundingMode values to disassembly suffixes.
935560Snate@binkert.org        static const char *roundingModeSuffix[];
945560Snate@binkert.org        /// Map enum TrappingMode values to FP disassembly suffixes.
955560Snate@binkert.org        static const char *fpTrappingModeSuffix[];
965560Snate@binkert.org        /// Map enum TrappingMode values to integer disassembly suffixes.
975560Snate@binkert.org        static const char *intTrappingModeSuffix[];
985560Snate@binkert.org
995560Snate@binkert.org        /// This instruction's rounding mode.
1005560Snate@binkert.org        RoundingMode roundingMode;
1015560Snate@binkert.org        /// This instruction's trapping mode.
1025560Snate@binkert.org        TrappingMode trappingMode;
1035560Snate@binkert.org
1045560Snate@binkert.org        /// Have we warned about this instruction's unsupported
1055560Snate@binkert.org        /// rounding mode (if applicable)?
1065560Snate@binkert.org        mutable bool warnedOnRounding;
1075560Snate@binkert.org
1085560Snate@binkert.org        /// Have we warned about this instruction's unsupported
1095560Snate@binkert.org        /// trapping mode (if applicable)?
1105560Snate@binkert.org        mutable bool warnedOnTrapping;
1115560Snate@binkert.org
1125560Snate@binkert.org        /// Constructor
1135560Snate@binkert.org        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
1145560Snate@binkert.org            : AlphaStaticInst(mnem, _machInst, __opClass),
1155560Snate@binkert.org              roundingMode((enum RoundingMode)FP_ROUNDMODE),
1165560Snate@binkert.org              trappingMode((enum TrappingMode)FP_TRAPMODE),
1175560Snate@binkert.org              warnedOnRounding(false),
1185560Snate@binkert.org              warnedOnTrapping(false)
1195560Snate@binkert.org        {
1205560Snate@binkert.org        }
1215560Snate@binkert.org
1222650Ssaidi@eecs.umich.edu        int getC99RoundingMode(uint64_t fpcr_val) const;
1235560Snate@binkert.org
1242650Ssaidi@eecs.umich.edu        // This differs from the AlphaStaticInst version only in
1255560Snate@binkert.org        // printing suffixes for non-default rounding & trapping modes.
1265560Snate@binkert.org        std::string
1275560Snate@binkert.org        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1285560Snate@binkert.org    };
1295560Snate@binkert.org
1305560Snate@binkert.org}};
1315560Snate@binkert.org
1322650Ssaidi@eecs.umich.edu
1337811Ssteve.reinhardt@amd.comoutput decoder {{
134    int
135    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
136    {
137        if (roundingMode == Dynamic) {
138            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
139        }
140        else {
141            return alphaToC99RoundingMode[roundingMode];
142        }
143    }
144
145    std::string
146    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
147    {
148        std::string mnem_str(mnemonic);
149
150#ifndef SS_COMPATIBLE_DISASSEMBLY
151        std::string suffix("");
152        suffix += ((_destRegIdx[0] >= FP_Reg_Base)
153                   ? fpTrappingModeSuffix[trappingMode]
154                   : intTrappingModeSuffix[trappingMode]);
155        suffix += roundingModeSuffix[roundingMode];
156
157        if (suffix != "") {
158            mnem_str = csprintf("%s/%s", mnemonic, suffix);
159        }
160#endif
161
162        std::stringstream ss;
163        ccprintf(ss, "%-10s ", mnem_str.c_str());
164
165        // just print the first two source regs... if there's
166        // a third one, it's a read-modify-write dest (Rc),
167        // e.g. for CMOVxx
168        if (_numSrcRegs > 0) {
169            printReg(ss, _srcRegIdx[0]);
170        }
171        if (_numSrcRegs > 1) {
172            ss << ",";
173            printReg(ss, _srcRegIdx[1]);
174        }
175
176        // just print the first dest... if there's a second one,
177        // it's generally implicit
178        if (_numDestRegs > 0) {
179            if (_numSrcRegs > 0)
180                ss << ",";
181            printReg(ss, _destRegIdx[0]);
182        }
183
184        return ss.str();
185    }
186
187    const int AlphaFP::alphaToC99RoundingMode[] = {
188        M5_FE_TOWARDZERO,       // Chopped
189        M5_FE_DOWNWARD, // Minus_Infinity
190        M5_FE_TONEAREST,        // Normal
191        M5_FE_UPWARD    // Dynamic in inst, Plus_Infinity in FPCR
192    };
193
194    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
195    // mark invalid trapping modes, but don't fail on them, because
196    // you could decode anything on a misspeculated path
197    const char *AlphaFP::fpTrappingModeSuffix[] =
198        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
199    const char *AlphaFP::intTrappingModeSuffix[] =
200        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
201}};
202
203// FP instruction class execute method template.  Handles non-standard
204// rounding modes.
205def template FloatingPointExecute {{
206    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
207                                  Trace::InstRecord *traceData) const
208    {
209        if (trappingMode != Imprecise && !warnedOnTrapping) {
210            warn("%s: non-standard trapping mode not supported",
211                 generateDisassembly(0, NULL));
212            warnedOnTrapping = true;
213        }
214
215        Fault fault = NoFault;
216
217        %(fp_enable_check)s;
218        %(op_decl)s;
219        %(op_rd)s;
220#if USE_FENV
221        if (roundingMode == Normal) {
222            %(code)s;
223        } else {
224            m5_fesetround(getC99RoundingMode(
225                           xc->readMiscReg(MISCREG_FPCR)));
226            %(code)s;
227            m5_fesetround(M5_FE_TONEAREST);
228        }
229#else
230        if (roundingMode != Normal && !warnedOnRounding) {
231            warn("%s: non-standard rounding mode not supported",
232                 generateDisassembly(0, NULL));
233            warnedOnRounding = true;
234        }
235        %(code)s;
236#endif
237
238        if (fault == NoFault) {
239            %(op_wb)s;
240        }
241
242        return fault;
243    }
244}};
245
246// FP instruction class execute method template where no dynamic
247// rounding mode control is needed.  Like BasicExecute, but includes
248// check & warning for non-standard trapping mode.
249def template FPFixedRoundingExecute {{
250    Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
251                                  Trace::InstRecord *traceData) const
252    {
253        if (trappingMode != Imprecise && !warnedOnTrapping) {
254            warn("%s: non-standard trapping mode not supported",
255                 generateDisassembly(0, NULL));
256            warnedOnTrapping = true;
257        }
258
259        Fault fault = NoFault;
260
261        %(fp_enable_check)s;
262        %(op_decl)s;
263        %(op_rd)s;
264        %(code)s;
265
266        if (fault == NoFault) {
267            %(op_wb)s;
268        }
269
270        return fault;
271    }
272}};
273
274def template FloatingPointDecode {{
275 {
276     AlphaStaticInst *i = new %(class_name)s(machInst);
277     if (FC == 31) {
278         i = makeNop(i);
279     }
280     return i;
281 }
282}};
283
284// General format for floating-point operate instructions:
285// - Checks trapping and rounding mode flags.  Trapping modes
286//   currently unimplemented (will fail).
287// - Generates NOP if FC == 31.
288def format FloatingPointOperate(code, *opt_args) {{
289    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
290    decode_block = FloatingPointDecode.subst(iop)
291    header_output = BasicDeclare.subst(iop)
292    decoder_output = BasicConstructor.subst(iop)
293    exec_output = FloatingPointExecute.subst(iop)
294}};
295
296// Special format for cvttq where rounding mode is pre-decoded
297def format FPFixedRounding(code, class_suffix, *opt_args) {{
298    Name += class_suffix
299    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
300    decode_block = FloatingPointDecode.subst(iop)
301    header_output = BasicDeclare.subst(iop)
302    decoder_output = BasicConstructor.subst(iop)
303    exec_output = FPFixedRoundingExecute.subst(iop)
304}};
305
306