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