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