fp.isa revision 4172
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#if FULL_SYSTEM
46    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
47    {
48        Fault fault = NoFault;	// dummy... this ipr access should not fault
49        if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) {
50            fault = new FloatEnableFault;
51        }
52        return fault;
53    }
54#else
55    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
56    {
57        return NoFault;
58    }
59#endif
60}};
61
62output header {{
63    /**
64     * Base class for general floating-point instructions.  Includes
65     * support for various Alpha rounding and trapping modes.  Only FP
66     * instructions that require this support are derived from this
67     * class; the rest derive directly from AlphaStaticInst.
68     */
69    class AlphaFP : public AlphaStaticInst
70    {
71      public:
72        /// Alpha FP rounding modes.
73        enum RoundingMode {
74            Chopped = 0,	///< round toward zero
75            Minus_Infinity = 1, ///< round toward minus infinity
76            Normal = 2,		///< round to nearest (default)
77            Dynamic = 3,	///< use FPCR setting (in instruction)
78            Plus_Infinity = 3	///< round to plus inifinity (in FPCR)
79        };
80
81        /// Alpha FP trapping modes.
82        /// For instructions that produce integer results, the
83        /// "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