fp.isa revision 8738
16145SN/A// -*- mode:c++ -*- 28683SN/A 36145SN/A// Copyright (c) 2007 MIPS Technologies, Inc. 46145SN/A// All rights reserved. 56145SN/A// 66145SN/A// Redistribution and use in source and binary forms, with or without 76145SN/A// modification, are permitted provided that the following conditions are 86145SN/A// met: redistributions of source code must retain the above copyright 96145SN/A// notice, this list of conditions and the following disclaimer; 106145SN/A// redistributions in binary form must reproduce the above copyright 116145SN/A// notice, this list of conditions and the following disclaimer in the 126145SN/A// documentation and/or other materials provided with the distribution; 136145SN/A// neither the name of the copyright holders nor the names of its 146145SN/A// contributors may be used to endorse or promote products derived from 156145SN/A// this software without specific prior written permission. 166145SN/A// 176145SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186145SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196145SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206145SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216145SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226145SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236145SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246145SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256145SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266145SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276145SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286145SN/A// 2910441Snilay@cs.wisc.edu// Authors: Korey Sewell 3010441Snilay@cs.wisc.edu 316145SN/A//////////////////////////////////////////////////////////////////// 327055SN/A// 336145SN/A// Floating Point operate instructions 346145SN/A// 357039SN/A 369104SN/Aoutput header {{ 3710301Snilay@cs.wisc.edu /** 389105SN/A * Base class for FP operations. 398174SN/A */ 407039SN/A class FPOp : public MipsStaticInst 417039SN/A { 427039SN/A protected: 4310301Snilay@cs.wisc.edu 4410301Snilay@cs.wisc.edu /// Constructor 4510301Snilay@cs.wisc.edu FPOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) 4610301Snilay@cs.wisc.edu { 477039SN/A } 487039SN/A 496145SN/A //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 507039SN/A 517039SN/A //needs function to check for fpEnable or not 527039SN/A }; 536876SN/A 547039SN/A class FPCompareOp : public FPOp 557039SN/A { 566145SN/A protected: 577039SN/A FPCompareOp(const char *mnem, MachInst _machInst, OpClass __opClass) : FPOp(mnem, _machInst, __opClass) 586145SN/A { 597039SN/A } 607039SN/A 618165SN/A std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 627039SN/A 636145SN/A }; 647039SN/A}}; 658165SN/A 667039SN/Aoutput decoder {{ 676145SN/A std::string FPCompareOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 687039SN/A { 697039SN/A std::stringstream ss; 706145SN/A 717039SN/A ccprintf(ss, "%-10s ", mnemonic); 727039SN/A 737039SN/A ccprintf(ss,"%d",CC); 747039SN/A 756145SN/A if(_numSrcRegs > 0) { 767039SN/A ss << ", "; 777839SN/A printReg(ss, _srcRegIdx[0]); 788193SN/A } 798193SN/A 808193SN/A if(_numSrcRegs > 1) { 818193SN/A ss << ", "; 826145SN/A printReg(ss, _srcRegIdx[1]); 837039SN/A } 847039SN/A 856145SN/A return ss.str(); 867039SN/A } 877039SN/A}}; 886145SN/A 897039SN/Aoutput exec {{ 907839SN/A inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 917839SN/A { 926145SN/A //@TODO: Implement correct CP0 checks to see if the CP1 939499SN/A // unit is enable or not 9410969Sdavid.hashe@amd.com if (!isCoprocessorEnabled(xc, 1)) 9510969Sdavid.hashe@amd.com return new CoprocessorUnusableFault(1); 9610969Sdavid.hashe@amd.com 976285SN/A return NoFault; 987039SN/A } 998683SN/A 1006145SN/A //If any operand is Nan return the appropriate QNaN 1017039SN/A template <class T> 1027039SN/A bool 1036145SN/A fpNanOperands(FPOp *inst, %(CPU_exec_context)s *xc, const T &src_type, 1047039SN/A Trace::InstRecord *traceData) 1057039SN/A { 1067039SN/A uint64_t mips_nan = 0; 1079692SN/A assert(sizeof(T) == 4); 1087039SN/A 1097055SN/A for (int i = 0; i < inst->numSrcRegs(); i++) { 1107055SN/A uint64_t src_bits = xc->readFloatRegOperandBits(inst, 0); 1116145SN/A 1129692SN/A if (isNan(&src_bits, 32) ) { 1139692SN/A mips_nan = MIPS32_QNAN; 1149692SN/A xc->setFloatRegOperandBits(inst, 0, mips_nan); 1156374SN/A if (traceData) { traceData->setData(mips_nan); } 1169692SN/A return true; 1179692SN/A } 1189692SN/A } 1199692SN/A return false; 1209692SN/A } 1219692SN/A 1229692SN/A template <class T> 1239692SN/A bool 1249692SN/A fpInvalidOp(FPOp *inst, %(CPU_exec_context)s *cpu, const T dest_val, 1259692SN/A Trace::InstRecord *traceData) 1269104SN/A { 1279104SN/A uint64_t mips_nan = 0; 1289104SN/A T src_op = dest_val; 1299104SN/A assert(sizeof(T) == 4); 1309104SN/A 1319104SN/A if (isNan(&src_op, 32)) { 1329105SN/A mips_nan = MIPS32_QNAN; 1339105SN/A 1349692SN/A //Set value to QNAN 1357039SN/A cpu->setFloatRegOperandBits(inst, 0, mips_nan); 1367039SN/A 13710314Snilay@cs.wisc.edu //Read FCSR from FloatRegFile 1386145SN/A uint32_t fcsr_bits = 1397039SN/A cpu->tcBase()->readFloatRegBits(FLOATREG_FCSR); 1407039SN/A 14110314Snilay@cs.wisc.edu uint32_t new_fcsr = genInvalidVector(fcsr_bits); 14210314Snilay@cs.wisc.edu 1437039SN/A //Write FCSR from FloatRegFile 1446145SN/A cpu->tcBase()->setFloatRegBits(FLOATREG_FCSR, new_fcsr); 1457039SN/A 1467039SN/A if (traceData) { traceData->setData(mips_nan); } 1477039SN/A return true; 1486145SN/A } 1497039SN/A 1509499SN/A return false; 1516145SN/A } 1527039SN/A 1537039SN/A void 1546285SN/A fpResetCauseBits(%(CPU_exec_context)s *cpu) 1557039SN/A { 1567039SN/A //Read FCSR from FloatRegFile 1577039SN/A uint32_t fcsr = cpu->tcBase()->readFloatRegBits(FLOATREG_FCSR); 1587454SN/A 1596145SN/A // TODO: Use utility function here 1607039SN/A fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0); 1616145SN/A 1629105SN/A //Write FCSR from FloatRegFile 1639105SN/A cpu->tcBase()->setFloatRegBits(FLOATREG_FCSR, fcsr); 1649105SN/A } 1657039SN/A}}; 1667055SN/A 1677039SN/Adef template FloatingPointExecute {{ 1687039SN/A Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const 1697039SN/A { 1707564SN/A Fault fault = NoFault; 1719105SN/A 1726145SN/A %(fp_enable_check)s; 1736145SN/A 1749554SN/A 1759554SN/A //When is the right time to reset cause bits? 17610441Snilay@cs.wisc.edu //start of every instruction or every cycle? 177 if (FullSystem) 178 fpResetCauseBits(xc); 179 %(op_decl)s; 180 %(op_rd)s; 181 182 //Check if any FP operand is a NaN value 183 if (!fpNanOperands((FPOp*)this, xc, Fd, traceData)) { 184 %(code)s; 185 186 //Change this code for Full-System/Sycall Emulation 187 //separation 188 //---- 189 //Should Full System-Mode throw a fault here? 190 //---- 191 //Check for IEEE 754 FP Exceptions 192 //fault = fpNanOperands((FPOp*)this, xc, Fd, traceData); 193 bool invalid_op = false; 194 if (FullSystem) { 195 invalid_op = 196 fpInvalidOp((FPOp*)this, xc, Fd, traceData); 197 } 198 if (!invalid_op && fault == NoFault) { 199 %(op_wb)s; 200 } 201 } 202 203 return fault; 204 } 205}}; 206 207// Primary format for float point operate instructions: 208def format FloatOp(code, *flags) {{ 209 iop = InstObjParams(name, Name, 'FPOp', code, flags) 210 header_output = BasicDeclare.subst(iop) 211 decoder_output = BasicConstructor.subst(iop) 212 decode_block = BasicDecode.subst(iop) 213 exec_output = FloatingPointExecute.subst(iop) 214}}; 215 216def format FloatCompareOp(cond_code, *flags) {{ 217 import sys 218 219 code = 'bool cond;\n' 220 if '_sf' in cond_code or 'SinglePrecision' in flags: 221 if 'QnanException' in flags: 222 code += 'if (isQnan(&Fs_sf, 32) || isQnan(&Ft_sf, 32)) {\n' 223 code += '\tFCSR = genInvalidVector(FCSR);\n' 224 code += '\treturn NoFault;' 225 code += '}\n else ' 226 code += 'if (isNan(&Fs_sf, 32) || isNan(&Ft_sf, 32)) {\n' 227 elif '_df' in cond_code or 'DoublePrecision' in flags: 228 if 'QnanException' in flags: 229 code += 'if (isQnan(&Fs_df, 64) || isQnan(&Ft_df, 64)) {\n' 230 code += '\tFCSR = genInvalidVector(FCSR);\n' 231 code += '\treturn NoFault;' 232 code += '}\n else ' 233 code += 'if (isNan(&Fs_df, 64) || isNan(&Ft_df, 64)) {\n' 234 else: 235 sys.exit('Decoder Failed: Can\'t Determine Operand Type\n') 236 237 if 'UnorderedTrue' in flags: 238 code += 'cond = 1;\n' 239 elif 'UnorderedFalse' in flags: 240 code += 'cond = 0;\n' 241 else: 242 sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') 243 244 code += '} else {\n' 245 code += cond_code + '}' 246 code += 'FCSR = genCCVector(FCSR, CC, cond);\n' 247 248 iop = InstObjParams(name, Name, 'FPCompareOp', code) 249 header_output = BasicDeclare.subst(iop) 250 decoder_output = BasicConstructor.subst(iop) 251 decode_block = BasicDecode.subst(iop) 252 exec_output = BasicExecute.subst(iop) 253}}; 254 255def format FloatConvertOp(code, *flags) {{ 256 import sys 257 258 #Determine Source Type 259 convert = 'fpConvert(' 260 if '_sf' in code: 261 code = 'float ' + code + '\n' 262 convert += 'SINGLE_TO_' 263 elif '_df' in code: 264 code = 'double ' + code + '\n' 265 convert += 'DOUBLE_TO_' 266 elif '_uw' in code: 267 code = 'uint32_t ' + code + '\n' 268 convert += 'WORD_TO_' 269 elif '_ud' in code: 270 code = 'uint64_t ' + code + '\n' 271 convert += 'LONG_TO_' 272 else: 273 sys.exit("Error Determining Source Type for Conversion") 274 275 #Determine Destination Type 276 if 'ToSingle' in flags: 277 code += 'Fd_uw = ' + convert + 'SINGLE, ' 278 elif 'ToDouble' in flags: 279 code += 'Fd_ud = ' + convert + 'DOUBLE, ' 280 elif 'ToWord' in flags: 281 code += 'Fd_uw = ' + convert + 'WORD, ' 282 elif 'ToLong' in flags: 283 code += 'Fd_ud = ' + convert + 'LONG, ' 284 else: 285 sys.exit("Error Determining Destination Type for Conversion") 286 287 #Figure out how to round value 288 if 'Ceil' in flags: 289 code += 'ceil(val)); ' 290 elif 'Floor' in flags: 291 code += 'floor(val)); ' 292 elif 'Round' in flags: 293 code += 'roundFP(val, 0)); ' 294 elif 'Trunc' in flags: 295 code += 'truncFP(val));' 296 else: 297 code += 'val); ' 298 299 iop = InstObjParams(name, Name, 'FPOp', code) 300 header_output = BasicDeclare.subst(iop) 301 decoder_output = BasicConstructor.subst(iop) 302 decode_block = BasicDecode.subst(iop) 303 exec_output = BasicExecute.subst(iop) 304}}; 305 306def format FloatAccOp(code, *flags) {{ 307 iop = InstObjParams(name, Name, 'FPOp', code, flags) 308 header_output = BasicDeclare.subst(iop) 309 decoder_output = BasicConstructor.subst(iop) 310 decode_block = BasicDecode.subst(iop) 311 exec_output = BasicExecute.subst(iop) 312}}; 313 314// Primary format for float64 operate instructions: 315def format Float64Op(code, *flags) {{ 316 iop = InstObjParams(name, Name, 'MipsStaticInst', code, flags) 317 header_output = BasicDeclare.subst(iop) 318 decoder_output = BasicConstructor.subst(iop) 319 decode_block = BasicDecode.subst(iop) 320 exec_output = BasicExecute.subst(iop) 321}}; 322 323def format FloatPSCompareOp(cond_code1, cond_code2, *flags) {{ 324 import sys 325 326 code = 'bool cond1, cond2;\n' 327 code += 'bool code_block1, code_block2;\n' 328 code += 'code_block1 = code_block2 = true;\n' 329 330 if 'QnanException' in flags: 331 code += 'if (isQnan(&Fs1_sf, 32) || isQnan(&Ft1_sf, 32)) {\n' 332 code += '\tFCSR = genInvalidVector(FCSR);\n' 333 code += 'code_block1 = false;' 334 code += '}\n' 335 code += 'if (isQnan(&Fs2_sf, 32) || isQnan(&Ft2_sf, 32)) {\n' 336 code += '\tFCSR = genInvalidVector(FCSR);\n' 337 code += 'code_block2 = false;' 338 code += '}\n' 339 340 code += 'if (code_block1) {' 341 code += '\tif (isNan(&Fs1_sf, 32) || isNan(&Ft1_sf, 32)) {\n' 342 if 'UnorderedTrue' in flags: 343 code += 'cond1 = 1;\n' 344 elif 'UnorderedFalse' in flags: 345 code += 'cond1 = 0;\n' 346 else: 347 sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') 348 code += '} else {\n' 349 code += cond_code1 350 code += 'FCSR = genCCVector(FCSR, CC, cond1);}\n}\n' 351 352 code += 'if (code_block2) {' 353 code += '\tif (isNan(&Fs2_sf, 32) || isNan(&Ft2_sf, 32)) {\n' 354 if 'UnorderedTrue' in flags: 355 code += 'cond2 = 1;\n' 356 elif 'UnorderedFalse' in flags: 357 code += 'cond2 = 0;\n' 358 else: 359 sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n') 360 code += '} else {\n' 361 code += cond_code2 362 code += 'FCSR = genCCVector(FCSR, CC, cond2);}\n}' 363 364 iop = InstObjParams(name, Name, 'FPCompareOp', code) 365 header_output = BasicDeclare.subst(iop) 366 decoder_output = BasicConstructor.subst(iop) 367 decode_block = BasicDecode.subst(iop) 368 exec_output = BasicExecute.subst(iop) 369}}; 370 371