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(ExecContext *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    inline Fault checkVectorEnableFault(ExecContext *xc) {
54        return std::make_shared<VectorEnableFault>();
55    }
56}};
57
58output header {{
59    /**
60     * Base class for general floating-point instructions.  Includes
61     * support for various Alpha rounding and trapping modes.  Only FP
62     * instructions that require this support are derived from this
63     * class; the rest derive directly from AlphaStaticInst.
64     */
65    class AlphaFP : public AlphaStaticInst
66    {
67      public:
68        /// Alpha FP rounding modes.
69        enum RoundingMode {
70            Chopped = 0,        ///< round toward zero
71            Minus_Infinity = 1, ///< round toward minus infinity
72            Normal = 2,         ///< round to nearest (default)
73            Dynamic = 3,        ///< use FPCR setting (in instruction)
74            Plus_Infinity = 3   ///< round to plus inifinity (in FPCR)
75        };
76
77        /// Alpha FP trapping modes.
78        /// For instructions that produce integer results, the
79        /// "Underflow Enable" modes really mean "Overflow Enable", and
80        /// the assembly modifier is V rather than U.
81        enum TrappingMode {
82            /// default: nothing enabled
83            Imprecise = 0,                 ///< no modifier
84            /// underflow/overflow traps enabled, inexact disabled
85            Underflow_Imprecise = 1,       ///< /U or /V
86            Underflow_Precise = 5,         ///< /SU or /SV
87            /// underflow/overflow and inexact traps enabled
88            Underflow_Inexact_Precise = 7  ///< /SUI or /SVI
89        };
90
91      protected:
92        /// Map Alpha rounding mode to C99 constants from <fenv.h>.
93        static const int alphaToC99RoundingMode[];
94
95        /// Map enum RoundingMode values to disassembly suffixes.
96        static const char *roundingModeSuffix[];
97        /// Map enum TrappingMode values to FP disassembly suffixes.
98        static const char *fpTrappingModeSuffix[];
99        /// Map enum TrappingMode values to integer disassembly suffixes.
100        static const char *intTrappingModeSuffix[];
101
102        /// This instruction's rounding mode.
103        RoundingMode roundingMode;
104        /// This instruction's trapping mode.
105        TrappingMode trappingMode;
106
107        /// Have we warned about this instruction's unsupported
108        /// rounding mode (if applicable)?
109        mutable bool warnedOnRounding;
110
111        /// Have we warned about this instruction's unsupported
112        /// trapping mode (if applicable)?
113        mutable bool warnedOnTrapping;
114
115        /// Constructor
116        AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
117            : AlphaStaticInst(mnem, _machInst, __opClass),
118              roundingMode((enum RoundingMode)FP_ROUNDMODE),
119              trappingMode((enum TrappingMode)FP_TRAPMODE),
120              warnedOnRounding(false),
121              warnedOnTrapping(false)
122        {
123        }
124
125        int getC99RoundingMode(uint64_t fpcr_val) const;
126
127        // This differs from the AlphaStaticInst version only in
128        // printing suffixes for non-default rounding & trapping modes.
129        std::string generateDisassembly(
130                Addr pc, const SymbolTable *symtab) const override;
131    };
132
133}};
134
135
136output decoder {{
137    int
138    AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
139    {
140        if (roundingMode == Dynamic) {
141            return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
142        }
143        else {
144            return alphaToC99RoundingMode[roundingMode];
145        }
146    }
147
148    std::string
149    AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
150    {
151        std::string mnem_str(mnemonic);
152
153#ifndef SS_COMPATIBLE_DISASSEMBLY
154        std::string suffix("");
155        suffix += ((_destRegIdx[0].isFloatReg())
156                   ? fpTrappingModeSuffix[trappingMode]
157                   : intTrappingModeSuffix[trappingMode]);
158        suffix += roundingModeSuffix[roundingMode];
159
160        if (suffix != "") {
161            mnem_str = csprintf("%s/%s", mnemonic, suffix);
162        }
163#endif
164
165        std::stringstream ss;
166        ccprintf(ss, "%-10s ", mnem_str.c_str());
167
168        // just print the first two source regs... if there's
169        // a third one, it's a read-modify-write dest (Rc),
170        // e.g. for CMOVxx
171        if (_numSrcRegs > 0) {
172            printReg(ss, _srcRegIdx[0]);
173        }
174        if (_numSrcRegs > 1) {
175            ss << ",";
176            printReg(ss, _srcRegIdx[1]);
177        }
178
179        // just print the first dest... if there's a second one,
180        // it's generally implicit
181        if (_numDestRegs > 0) {
182            if (_numSrcRegs > 0)
183                ss << ",";
184            printReg(ss, _destRegIdx[0]);
185        }
186
187        return ss.str();
188    }
189
190    const int AlphaFP::alphaToC99RoundingMode[] = {
191        M5_FE_TOWARDZERO,       // Chopped
192        M5_FE_DOWNWARD, // Minus_Infinity
193        M5_FE_TONEAREST,        // Normal
194        M5_FE_UPWARD    // Dynamic in inst, Plus_Infinity in FPCR
195    };
196
197    const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
198    // mark invalid trapping modes, but don't fail on them, because
199    // you could decode anything on a misspeculated path
200    const char *AlphaFP::fpTrappingModeSuffix[] =
201        { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
202    const char *AlphaFP::intTrappingModeSuffix[] =
203        { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
204}};
205
206// FP instruction class execute method template.  Handles non-standard
207// rounding modes.
208def template FloatingPointExecute {{
209    Fault %(class_name)s::execute(ExecContext *xc,
210                                  Trace::InstRecord *traceData) const
211    {
212        if (trappingMode != Imprecise && !warnedOnTrapping) {
213            warn("%s: non-standard trapping mode not supported",
214                 generateDisassembly(0, NULL));
215            warnedOnTrapping = true;
216        }
217
218        Fault fault = NoFault;
219
220        %(fp_enable_check)s;
221        %(op_decl)s;
222        %(op_rd)s;
223#if USE_FENV
224        if (roundingMode == Normal) {
225            %(code)s;
226        } else {
227            m5_fesetround(getC99RoundingMode(
228                           xc->readMiscReg(MISCREG_FPCR)));
229            %(code)s;
230            m5_fesetround(M5_FE_TONEAREST);
231        }
232#else
233        if (roundingMode != Normal && !warnedOnRounding) {
234            warn("%s: non-standard rounding mode not supported",
235                 generateDisassembly(0, NULL));
236            warnedOnRounding = true;
237        }
238        %(code)s;
239#endif
240
241        if (fault == NoFault) {
242            %(op_wb)s;
243        }
244
245        return fault;
246    }
247}};
248
249// FP instruction class execute method template where no dynamic
250// rounding mode control is needed.  Like BasicExecute, but includes
251// check & warning for non-standard trapping mode.
252def template FPFixedRoundingExecute {{
253    Fault %(class_name)s::execute(ExecContext *xc,
254                                  Trace::InstRecord *traceData) const
255    {
256        if (trappingMode != Imprecise && !warnedOnTrapping) {
257            warn("%s: non-standard trapping mode not supported",
258                 generateDisassembly(0, NULL));
259            warnedOnTrapping = true;
260        }
261
262        Fault fault = NoFault;
263
264        %(fp_enable_check)s;
265        %(op_decl)s;
266        %(op_rd)s;
267        %(code)s;
268
269        if (fault == NoFault) {
270            %(op_wb)s;
271        }
272
273        return fault;
274    }
275}};
276
277def template FloatingPointDecode {{
278 {
279     AlphaStaticInst *i = new %(class_name)s(machInst);
280     if (FC == 31) {
281         i = makeNop(i);
282     }
283     return i;
284 }
285}};
286
287// General format for floating-point operate instructions:
288// - Checks trapping and rounding mode flags.  Trapping modes
289//   currently unimplemented (will fail).
290// - Generates NOP if FC == 31.
291def format FloatingPointOperate(code, *opt_args) {{
292    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
293    decode_block = FloatingPointDecode.subst(iop)
294    header_output = BasicDeclare.subst(iop)
295    decoder_output = BasicConstructor.subst(iop)
296    exec_output = FloatingPointExecute.subst(iop)
297}};
298
299// Special format for cvttq where rounding mode is pre-decoded
300def format FPFixedRounding(code, class_suffix, *opt_args) {{
301    Name += class_suffix
302    iop = InstObjParams(name, Name, 'AlphaFP', code, opt_args)
303    decode_block = FloatingPointDecode.subst(iop)
304    header_output = BasicDeclare.subst(iop)
305    decoder_output = BasicConstructor.subst(iop)
306    exec_output = FPFixedRoundingExecute.subst(iop)
307}};
308
309