base.isa revision 7720
1// Copyright (c) 2006-2007 The Regents of The University of Michigan 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer; 8// redistributions in binary form must reproduce the above copyright 9// notice, this list of conditions and the following disclaimer in the 10// documentation and/or other materials provided with the distribution; 11// neither the name of the copyright holders nor the names of its 12// contributors may be used to endorse or promote products derived from 13// this software without specific prior written permission. 14// 15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26// 27// Authors: Ali Saidi 28// Gabe Black 29// Steve Reinhardt 30 31//////////////////////////////////////////////////////////////////// 32// 33// Base class for sparc instructions, and some support functions 34// 35 36output header {{ 37 38 union CondCodes 39 { 40 struct 41 { 42 uint8_t c:1; 43 uint8_t v:1; 44 uint8_t z:1; 45 uint8_t n:1; 46 }; 47 uint32_t bits; 48 }; 49 50 enum CondTest 51 { 52 Always=0x8, 53 Never=0x0, 54 NotEqual=0x9, 55 Equal=0x1, 56 Greater=0xA, 57 LessOrEqual=0x2, 58 GreaterOrEqual=0xB, 59 Less=0x3, 60 GreaterUnsigned=0xC, 61 LessOrEqualUnsigned=0x4, 62 CarryClear=0xD, 63 CarrySet=0x5, 64 Positive=0xE, 65 Negative=0x6, 66 OverflowClear=0xF, 67 OverflowSet=0x7 68 }; 69 70 enum FpCondTest 71 { 72 FAlways=0x8, 73 FNever=0x0, 74 FUnordered=0x7, 75 FGreater=0x6, 76 FUnorderedOrGreater=0x5, 77 FLess=0x4, 78 FUnorderedOrLess=0x3, 79 FLessOrGreater=0x2, 80 FNotEqual=0x1, 81 FEqual=0x9, 82 FUnorderedOrEqual=0xA, 83 FGreaterOrEqual=0xB, 84 FUnorderedOrGreaterOrEqual=0xC, 85 FLessOrEqual=0xD, 86 FUnorderedOrLessOrEqual=0xE, 87 FOrdered=0xF 88 }; 89 90 extern const char *CondTestAbbrev[]; 91 92 /** 93 * Base class for all SPARC static instructions. 94 */ 95 class SparcStaticInst : public StaticInst 96 { 97 protected: 98 // Constructor. 99 SparcStaticInst(const char *mnem, 100 ExtMachInst _machInst, OpClass __opClass) 101 : StaticInst(mnem, _machInst, __opClass) 102 { 103 } 104 105 std::string generateDisassembly(Addr pc, 106 const SymbolTable *symtab) const; 107 108 void printReg(std::ostream &os, int reg) const; 109 void printSrcReg(std::ostream &os, int reg) const; 110 void printDestReg(std::ostream &os, int reg) const; 111 112 void printRegArray(std::ostream &os, 113 const RegIndex indexArray[], int num) const; 114 115 void advancePC(SparcISA::PCState &pcState) const; 116 }; 117 118 bool passesFpCondition(uint32_t fcc, uint32_t condition); 119 120 bool passesCondition(uint32_t codes, uint32_t condition); 121 122 inline int64_t sign_ext(uint64_t data, int origWidth) 123 { 124 int shiftAmount = 64 - origWidth; 125 return (((int64_t)data) << shiftAmount) >> shiftAmount; 126 } 127}}; 128 129output decoder {{ 130 131 const char *CondTestAbbrev[] = 132 { 133 "nev", //Never 134 "e", //Equal 135 "le", //Less or Equal 136 "l", //Less 137 "leu", //Less or Equal Unsigned 138 "c", //Carry set 139 "n", //Negative 140 "o", //Overflow set 141 "a", //Always 142 "ne", //Not Equal 143 "g", //Greater 144 "ge", //Greater or Equal 145 "gu", //Greater Unsigned 146 "cc", //Carry clear 147 "p", //Positive 148 "oc" //Overflow Clear 149 }; 150}}; 151 152def template ROrImmDecode {{ 153 { 154 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) 155 : (SparcStaticInst *)(new %(class_name)s(machInst))); 156 } 157}}; 158 159output header {{ 160 union DoubleSingle 161 { 162 double d; 163 uint64_t ui; 164 uint32_t s[2]; 165 DoubleSingle(double _d) : d(_d) 166 {} 167 DoubleSingle(uint64_t _ui) : ui(_ui) 168 {} 169 DoubleSingle(uint32_t _s0, uint32_t _s1) 170 { 171 s[0] = _s0; 172 s[1] = _s1; 173 } 174 }; 175}}; 176 177let {{ 178 def filterDoubles(code): 179 assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 180 for opName in ("Frd", "Frs1", "Frs2", "Frd_N"): 181 next_pos = 0 182 operandsREString = (r''' 183 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 184 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 185 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 186 ''' % opName) 187 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 188 is_src = False 189 is_dest = False 190 extension = None 191 foundOne = False 192 while 1: 193 match = operandsRE.search(code, next_pos) 194 if not match: 195 break 196 foundOne = True 197 op = match.groups() 198 (op_full, op_base, op_ext) = op 199 is_dest_local = (assignRE.match(code, match.end()) != None) 200 is_dest = is_dest or is_dest_local 201 is_src = is_src or not is_dest_local 202 if extension and extension != op_ext: 203 raise Exception, "Inconsistent extensions in double filter." 204 extension = op_ext 205 next_pos = match.end() 206 if foundOne: 207 # Get rid of any unwanted extension 208 code = operandsRE.sub(op_base, code) 209 is_int = False 210 member = "d" 211 if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"): 212 is_int = True 213 member = "ui" 214 if is_src: 215 code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \ 216 (opName, opName, opName, member)) + code 217 if is_dest: 218 code += ''' 219 %s_low = DoubleSingle(%s).s[1]; 220 %s_high = DoubleSingle(%s).s[0];''' % \ 221 (opName, opName, opName, opName) 222 if is_int: 223 code = ("uint64_t %s;" % opName) + code 224 else: 225 code = ("double %s;" % opName) + code 226 return code 227}}; 228 229let {{ 230 def splitOutImm(code): 231 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?') 232 rOrImmMatch = matcher.search(code) 233 if (rOrImmMatch == None): 234 return (False, code, '', '', '') 235 rString = rOrImmMatch.group("rNum") 236 if (rOrImmMatch.group("typeQual") != None): 237 rString += rOrImmMatch.group("typeQual") 238 iString = rOrImmMatch.group("iNum") 239 orig_code = code 240 code = matcher.sub('Rs' + rString, orig_code) 241 imm_code = matcher.sub('imm', orig_code) 242 return (True, code, imm_code, rString, iString) 243}}; 244 245output decoder {{ 246 247 inline void printMnemonic(std::ostream &os, const char * mnemonic) 248 { 249 ccprintf(os, "\t%s ", mnemonic); 250 } 251 252 void SparcStaticInst::printRegArray(std::ostream &os, 253 const RegIndex indexArray[], int num) const 254 { 255 if(num <= 0) 256 return; 257 printReg(os, indexArray[0]); 258 for(int x = 1; x < num; x++) 259 { 260 os << ", "; 261 printReg(os, indexArray[x]); 262 } 263 } 264 265 void 266 SparcStaticInst::advancePC(SparcISA::PCState &pcState) const 267 { 268 pcState.advance(); 269 } 270 271 void 272 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const 273 { 274 if(_numSrcRegs > reg) 275 printReg(os, _srcRegIdx[reg]); 276 } 277 278 void 279 SparcStaticInst::printDestReg(std::ostream &os, int reg) const 280 { 281 if(_numDestRegs > reg) 282 printReg(os, _destRegIdx[reg]); 283 } 284 285 void 286 SparcStaticInst::printReg(std::ostream &os, int reg) const 287 { 288 const int MaxGlobal = 8; 289 const int MaxOutput = 16; 290 const int MaxLocal = 24; 291 const int MaxInput = 32; 292 const int MaxMicroReg = 40; 293 if (reg < FP_Base_DepTag) { 294 //If we used a register from the next or previous window, 295 //take out the offset. 296 while (reg >= MaxMicroReg) 297 reg -= MaxMicroReg; 298 if (reg == FramePointerReg) 299 ccprintf(os, "%%fp"); 300 else if (reg == StackPointerReg) 301 ccprintf(os, "%%sp"); 302 else if(reg < MaxGlobal) 303 ccprintf(os, "%%g%d", reg); 304 else if(reg < MaxOutput) 305 ccprintf(os, "%%o%d", reg - MaxGlobal); 306 else if(reg < MaxLocal) 307 ccprintf(os, "%%l%d", reg - MaxOutput); 308 else if(reg < MaxInput) 309 ccprintf(os, "%%i%d", reg - MaxLocal); 310 else if(reg < MaxMicroReg) 311 ccprintf(os, "%%u%d", reg - MaxInput); 312 //The fake int regs that are really control regs 313 else { 314 switch (reg - MaxMicroReg) { 315 case 1: 316 ccprintf(os, "%%y"); 317 break; 318 case 2: 319 ccprintf(os, "%%ccr"); 320 break; 321 case 3: 322 ccprintf(os, "%%cansave"); 323 break; 324 case 4: 325 ccprintf(os, "%%canrestore"); 326 break; 327 case 5: 328 ccprintf(os, "%%cleanwin"); 329 break; 330 case 6: 331 ccprintf(os, "%%otherwin"); 332 break; 333 case 7: 334 ccprintf(os, "%%wstate"); 335 break; 336 } 337 } 338 } else if (reg < Ctrl_Base_DepTag) { 339 ccprintf(os, "%%f%d", reg - FP_Base_DepTag); 340 } else { 341 switch (reg - Ctrl_Base_DepTag) { 342 case MISCREG_ASI: 343 ccprintf(os, "%%asi"); 344 break; 345 case MISCREG_FPRS: 346 ccprintf(os, "%%fprs"); 347 break; 348 case MISCREG_PCR: 349 ccprintf(os, "%%pcr"); 350 break; 351 case MISCREG_PIC: 352 ccprintf(os, "%%pic"); 353 break; 354 case MISCREG_GSR: 355 ccprintf(os, "%%gsr"); 356 break; 357 case MISCREG_SOFTINT: 358 ccprintf(os, "%%softint"); 359 break; 360 case MISCREG_SOFTINT_SET: 361 ccprintf(os, "%%softint_set"); 362 break; 363 case MISCREG_SOFTINT_CLR: 364 ccprintf(os, "%%softint_clr"); 365 break; 366 case MISCREG_TICK_CMPR: 367 ccprintf(os, "%%tick_cmpr"); 368 break; 369 case MISCREG_STICK: 370 ccprintf(os, "%%stick"); 371 break; 372 case MISCREG_STICK_CMPR: 373 ccprintf(os, "%%stick_cmpr"); 374 break; 375 case MISCREG_TPC: 376 ccprintf(os, "%%tpc"); 377 break; 378 case MISCREG_TNPC: 379 ccprintf(os, "%%tnpc"); 380 break; 381 case MISCREG_TSTATE: 382 ccprintf(os, "%%tstate"); 383 break; 384 case MISCREG_TT: 385 ccprintf(os, "%%tt"); 386 break; 387 case MISCREG_TICK: 388 ccprintf(os, "%%tick"); 389 break; 390 case MISCREG_TBA: 391 ccprintf(os, "%%tba"); 392 break; 393 case MISCREG_PSTATE: 394 ccprintf(os, "%%pstate"); 395 break; 396 case MISCREG_TL: 397 ccprintf(os, "%%tl"); 398 break; 399 case MISCREG_PIL: 400 ccprintf(os, "%%pil"); 401 break; 402 case MISCREG_CWP: 403 ccprintf(os, "%%cwp"); 404 break; 405 case MISCREG_GL: 406 ccprintf(os, "%%gl"); 407 break; 408 case MISCREG_HPSTATE: 409 ccprintf(os, "%%hpstate"); 410 break; 411 case MISCREG_HTSTATE: 412 ccprintf(os, "%%htstate"); 413 break; 414 case MISCREG_HINTP: 415 ccprintf(os, "%%hintp"); 416 break; 417 case MISCREG_HTBA: 418 ccprintf(os, "%%htba"); 419 break; 420 case MISCREG_HSTICK_CMPR: 421 ccprintf(os, "%%hstick_cmpr"); 422 break; 423 case MISCREG_HVER: 424 ccprintf(os, "%%hver"); 425 break; 426 case MISCREG_STRAND_STS_REG: 427 ccprintf(os, "%%strand_sts_reg"); 428 break; 429 case MISCREG_FSR: 430 ccprintf(os, "%%fsr"); 431 break; 432 default: 433 ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); 434 } 435 } 436 } 437 438 std::string SparcStaticInst::generateDisassembly(Addr pc, 439 const SymbolTable *symtab) const 440 { 441 std::stringstream ss; 442 443 printMnemonic(ss, mnemonic); 444 445 // just print the first two source regs... if there's 446 // a third one, it's a read-modify-write dest (Rc), 447 // e.g. for CMOVxx 448 if(_numSrcRegs > 0) 449 { 450 printReg(ss, _srcRegIdx[0]); 451 } 452 if(_numSrcRegs > 1) 453 { 454 ss << ","; 455 printReg(ss, _srcRegIdx[1]); 456 } 457 458 // just print the first dest... if there's a second one, 459 // it's generally implicit 460 if(_numDestRegs > 0) 461 { 462 if(_numSrcRegs > 0) 463 ss << ","; 464 printReg(ss, _destRegIdx[0]); 465 } 466 467 return ss.str(); 468 } 469 470 bool passesFpCondition(uint32_t fcc, uint32_t condition) 471 { 472 bool u = (fcc == 3); 473 bool g = (fcc == 2); 474 bool l = (fcc == 1); 475 bool e = (fcc == 0); 476 switch(condition) 477 { 478 case FAlways: 479 return 1; 480 case FNever: 481 return 0; 482 case FUnordered: 483 return u; 484 case FGreater: 485 return g; 486 case FUnorderedOrGreater: 487 return u || g; 488 case FLess: 489 return l; 490 case FUnorderedOrLess: 491 return u || l; 492 case FLessOrGreater: 493 return l || g; 494 case FNotEqual: 495 return l || g || u; 496 case FEqual: 497 return e; 498 case FUnorderedOrEqual: 499 return u || e; 500 case FGreaterOrEqual: 501 return g || e; 502 case FUnorderedOrGreaterOrEqual: 503 return u || g || e; 504 case FLessOrEqual: 505 return l || e; 506 case FUnorderedOrLessOrEqual: 507 return u || l || e; 508 case FOrdered: 509 return e || l || g; 510 } 511 panic("Tried testing condition nonexistant " 512 "condition code %d", condition); 513 } 514 515 bool passesCondition(uint32_t codes, uint32_t condition) 516 { 517 CondCodes condCodes; 518 condCodes.bits = 0; 519 condCodes.c = codes & 0x1 ? 1 : 0; 520 condCodes.v = codes & 0x2 ? 1 : 0; 521 condCodes.z = codes & 0x4 ? 1 : 0; 522 condCodes.n = codes & 0x8 ? 1 : 0; 523 524 switch(condition) 525 { 526 case Always: 527 return true; 528 case Never: 529 return false; 530 case NotEqual: 531 return !condCodes.z; 532 case Equal: 533 return condCodes.z; 534 case Greater: 535 return !(condCodes.z | (condCodes.n ^ condCodes.v)); 536 case LessOrEqual: 537 return condCodes.z | (condCodes.n ^ condCodes.v); 538 case GreaterOrEqual: 539 return !(condCodes.n ^ condCodes.v); 540 case Less: 541 return (condCodes.n ^ condCodes.v); 542 case GreaterUnsigned: 543 return !(condCodes.c | condCodes.z); 544 case LessOrEqualUnsigned: 545 return (condCodes.c | condCodes.z); 546 case CarryClear: 547 return !condCodes.c; 548 case CarrySet: 549 return condCodes.c; 550 case Positive: 551 return !condCodes.n; 552 case Negative: 553 return condCodes.n; 554 case OverflowClear: 555 return !condCodes.v; 556 case OverflowSet: 557 return condCodes.v; 558 } 559 panic("Tried testing condition nonexistant " 560 "condition code %d", condition); 561 } 562}}; 563 564output exec {{ 565 /// Check "FP enabled" machine status bit. Called when executing any FP 566 /// instruction in full-system mode. 567 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled 568 /// if not. Non-full-system mode: always returns NoFault. 569#if FULL_SYSTEM 570 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 571 { 572 Fault fault = NoFault; // dummy... this ipr access should not fault 573 if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef && 574 xc->readMiscReg(MISCREG_FPRS) & 0x4) 575 return NoFault; 576 else 577 return new FpDisabled; 578 } 579#else 580 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 581 { 582 return NoFault; 583 } 584#endif 585}}; 586 587 588