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