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