fp.isa revision 12106
1// -*- mode:c++ -*-
2
3// Copyright (c) 2003-2005 The Regents of The University of Michigan
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Floating-point instructions
34//
35//      Note that many FP-type instructions which do not support all the
36//      various rounding & trapping modes use the simpler format
37//      BasicOperateWithNopCheck.
38//
39
40output exec {{
41    /// Check "FP enabled" machine status bit.  Called when executing any FP
42    /// instruction in full-system mode.
43    /// @retval Full-system mode: NoFault if FP is enabled, FenFault
44    /// if not.  Non-full-system mode: always returns NoFault.
45    inline Fault checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
46    {
47        Fault fault = NoFault;  // dummy... this ipr access should not fault
48        if (FullSystem && !ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
49            fault = std::make_shared<FloatEnableFault>();
50        }
51        return fault;
52    }
53}};
54
55output header {{
56    /**
57     * Base class for general floating-point instructions.  Includes
58     * support for various Alpha rounding and trapping modes.  Only FP
59     * instructions that require this support are derived from this
60     * class; the rest derive directly from AlphaStaticInst.
61     */
62    class AlphaFP : public AlphaStaticInst
63    {
64      public:
65        /// Alpha FP rounding modes.
66        enum RoundingMode {
67            Chopped = 0,        ///< round toward zero
68            Minus_Infinity = 1, ///< round toward minus infinity
69            Normal = 2,         ///< round to nearest (default)
70            Dynamic = 3,        ///< use FPCR setting (in instruction)
71            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
72        };
73
74        /// Alpha FP trapping modes.
75        /// For instructions that produce integer results, the
76        /// "Underflow Enable" modes really mean "Overflow Enable", and
77        /// the assembly modifier is V rather than U.
78        enum TrappingMode {
79            /// default: nothing enabled
80            Imprecise = 0,                 ///< no modifier
81            /// underflow/overflow traps enabled, inexact disabled
82            Underflow_Imprecise = 1,       ///< /U or /V
83            Underflow_Precise = 5,         ///< /SU or /SV
84            /// underflow/overflow and inexact traps enabled
85            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
86        };
87
88      protected:
89        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
90        static const int alphaToC99RoundingMode[];
91
92        /// Map enum RoundingMode values to disassembly suffixes.
93        static const char *roundingModeSuffix[];
94        /// Map enum TrappingMode values to FP disassembly suffixes.
95        static const char *fpTrappingModeSuffix[];
96        /// Map enum TrappingMode values to integer disassembly suffixes.
97        static const char *intTrappingModeSuffix[];
98
99        /// This instruction's rounding mode.
100        RoundingMode roundingMode;
101        /// This instruction's trapping mode.
102        TrappingMode trappingMode;
103
104        /// Have we warned about this instruction's unsupported
105        /// rounding mode (if applicable)?
106        mutable bool warnedOnRounding;
107
108        /// Have we warned about this instruction's unsupported
109        /// trapping mode (if applicable)?
110        mutable bool warnedOnTrapping;
111
112        /// Constructor
113        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
114            : AlphaStaticInst(mnem, _machInst, __opClass),
115              roundingMode((enum RoundingMode)FP_ROUNDMODE),
116              trappingMode((enum TrappingMode)FP_TRAPMODE),
117              warnedOnRounding(false),
118              warnedOnTrapping(false)
119        {
120        }
121
122        int getC99RoundingMode(uint64_t fpcr_val) const;
123
124        // This differs from the AlphaStaticInst version only in
125        // printing suffixes for non-default rounding & trapping modes.
126        std::string
127        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
128    };
129
130}};
131
132
133output 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].isFloatReg())
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