base.isa revision 4362
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 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 116 bool passesFpCondition(uint32_t fcc, uint32_t condition); 117 118 bool passesCondition(uint32_t codes, uint32_t condition); 119 120 inline int64_t sign_ext(uint64_t data, int origWidth) 121 { 122 int shiftAmount = 64 - origWidth; 123 return (((int64_t)data) << shiftAmount) >> shiftAmount; 124 } 125}}; 126 127output decoder {{ 128 129 char * CondTestAbbrev[] = 130 { 131 "nev", //Never 132 "e", //Equal 133 "le", //Less or Equal 134 "l", //Less 135 "leu", //Less or Equal Unsigned 136 "c", //Carry set 137 "n", //Negative 138 "o", //Overflow set 139 "a", //Always 140 "ne", //Not Equal 141 "g", //Greater 142 "ge", //Greater or Equal 143 "gu", //Greater Unsigned 144 "cc", //Carry clear 145 "p", //Positive 146 "oc" //Overflow Clear 147 }; 148}}; 149 150def template ROrImmDecode {{ 151 { 152 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) 153 : (SparcStaticInst *)(new %(class_name)s(machInst))); 154 } 155}}; 156 157output header {{ 158 union DoubleSingle 159 { 160 double d; 161 uint64_t ui; 162 uint32_t s[2]; 163 DoubleSingle(double _d) : d(_d) 164 {} 165 DoubleSingle(uint64_t _ui) : ui(_ui) 166 {} 167 DoubleSingle(uint32_t _s0, uint32_t _s1) 168 { 169 s[0] = _s0; 170 s[1] = _s1; 171 } 172 }; 173}}; 174 175let {{ 176 def filterDoubles(code): 177 assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 178 for opName in ("Frd", "Frs1", "Frs2", "Frd_N"): 179 next_pos = 0 180 operandsREString = (r''' 181 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 182 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 183 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 184 ''' % opName) 185 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 186 is_src = False 187 is_dest = False 188 extension = None 189 foundOne = False 190 while 1: 191 match = operandsRE.search(code, next_pos) 192 if not match: 193 break 194 foundOne = True 195 op = match.groups() 196 (op_full, op_base, op_ext) = op 197 is_dest_local = (assignRE.match(code, match.end()) != None) 198 is_dest = is_dest or is_dest_local 199 is_src = is_src or not is_dest_local 200 if extension and extension != op_ext: 201 raise Exception, "Inconsistent extensions in double filter." 202 extension = op_ext 203 next_pos = match.end() 204 if foundOne: 205 # Get rid of any unwanted extension 206 code = operandsRE.sub(op_base, code) 207 is_int = False 208 member = "d" 209 if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"): 210 is_int = True 211 member = "ui" 212 if is_src: 213 code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \ 214 (opName, opName, opName, member)) + code 215 if is_dest: 216 code += ''' 217 %s_low = DoubleSingle(%s).s[1]; 218 %s_high = DoubleSingle(%s).s[0];''' % \ 219 (opName, opName, opName, opName) 220 if is_int: 221 code = ("uint64_t %s;" % opName) + code 222 else: 223 code = ("double %s;" % opName) + code 224 return code 225}}; 226 227let {{ 228 def splitOutImm(code): 229 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?') 230 rOrImmMatch = matcher.search(code) 231 if (rOrImmMatch == None): 232 return (False, code, '', '', '') 233 rString = rOrImmMatch.group("rNum") 234 if (rOrImmMatch.group("typeQual") != None): 235 rString += rOrImmMatch.group("typeQual") 236 iString = rOrImmMatch.group("iNum") 237 orig_code = code 238 code = matcher.sub('Rs' + rString, orig_code) 239 imm_code = matcher.sub('imm', orig_code) 240 return (True, code, imm_code, rString, iString) 241}}; 242 243output decoder {{ 244 245 inline void printMnemonic(std::ostream &os, const char * mnemonic) 246 { 247 ccprintf(os, "\t%s ", mnemonic); 248 } 249 250 void SparcStaticInst::printRegArray(std::ostream &os, 251 const RegIndex indexArray[], int num) const 252 { 253 if(num <= 0) 254 return; 255 printReg(os, indexArray[0]); 256 for(int x = 1; x < num; x++) 257 { 258 os << ", "; 259 printReg(os, indexArray[x]); 260 } 261 } 262 263 void 264 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const 265 { 266 if(_numSrcRegs > reg) 267 printReg(os, _srcRegIdx[reg]); 268 } 269 270 void 271 SparcStaticInst::printDestReg(std::ostream &os, int reg) const 272 { 273 if(_numDestRegs > reg) 274 printReg(os, _destRegIdx[reg]); 275 } 276 277 void 278 SparcStaticInst::printReg(std::ostream &os, int reg) const 279 { 280 const int MaxGlobal = 8; 281 const int MaxOutput = 16; 282 const int MaxLocal = 24; 283 const int MaxInput = 32; 284 const int MaxMicroReg = 40; 285 if (reg < FP_Base_DepTag) { 286 //If we used a register from the next or previous window, 287 //take out the offset. 288 while (reg >= MaxMicroReg) 289 reg -= MaxMicroReg; 290 if (reg == FramePointerReg) 291 ccprintf(os, "%%fp"); 292 else if (reg == StackPointerReg) 293 ccprintf(os, "%%sp"); 294 else if(reg < MaxGlobal) 295 ccprintf(os, "%%g%d", reg); 296 else if(reg < MaxOutput) 297 ccprintf(os, "%%o%d", reg - MaxGlobal); 298 else if(reg < MaxLocal) 299 ccprintf(os, "%%l%d", reg - MaxOutput); 300 else if(reg < MaxInput) 301 ccprintf(os, "%%i%d", reg - MaxLocal); 302 else if(reg < MaxMicroReg) 303 ccprintf(os, "%%u%d", reg - MaxInput); 304 //The fake int regs that are really control regs 305 else { 306 switch (reg - MaxMicroReg) { 307 case 1: 308 ccprintf(os, "%%y"); 309 break; 310 case 2: 311 ccprintf(os, "%%ccr"); 312 break; 313 case 3: 314 ccprintf(os, "%%cansave"); 315 break; 316 case 4: 317 ccprintf(os, "%%canrestore"); 318 break; 319 case 5: 320 ccprintf(os, "%%cleanwin"); 321 break; 322 case 6: 323 ccprintf(os, "%%otherwin"); 324 break; 325 case 7: 326 ccprintf(os, "%%wstate"); 327 break; 328 } 329 } 330 } else if (reg < Ctrl_Base_DepTag) { 331 ccprintf(os, "%%f%d", reg - FP_Base_DepTag); 332 } else { 333 switch (reg - Ctrl_Base_DepTag) { 334 case MISCREG_ASI: 335 ccprintf(os, "%%asi"); 336 break; 337 case MISCREG_FPRS: 338 ccprintf(os, "%%fprs"); 339 break; 340 case MISCREG_PCR: 341 ccprintf(os, "%%pcr"); 342 break; 343 case MISCREG_PIC: 344 ccprintf(os, "%%pic"); 345 break; 346 case MISCREG_GSR: 347 ccprintf(os, "%%gsr"); 348 break; 349 case MISCREG_SOFTINT: 350 ccprintf(os, "%%softint"); 351 break; 352 case MISCREG_SOFTINT_SET: 353 ccprintf(os, "%%softint_set"); 354 break; 355 case MISCREG_SOFTINT_CLR: 356 ccprintf(os, "%%softint_clr"); 357 break; 358 case MISCREG_TICK_CMPR: 359 ccprintf(os, "%%tick_cmpr"); 360 break; 361 case MISCREG_STICK: 362 ccprintf(os, "%%stick"); 363 break; 364 case MISCREG_STICK_CMPR: 365 ccprintf(os, "%%stick_cmpr"); 366 break; 367 case MISCREG_TPC: 368 ccprintf(os, "%%tpc"); 369 break; 370 case MISCREG_TNPC: 371 ccprintf(os, "%%tnpc"); 372 break; 373 case MISCREG_TSTATE: 374 ccprintf(os, "%%tstate"); 375 break; 376 case MISCREG_TT: 377 ccprintf(os, "%%tt"); 378 break; 379 case MISCREG_TICK: 380 ccprintf(os, "%%tick"); 381 break; 382 case MISCREG_TBA: 383 ccprintf(os, "%%tba"); 384 break; 385 case MISCREG_PSTATE: 386 ccprintf(os, "%%pstate"); 387 break; 388 case MISCREG_TL: 389 ccprintf(os, "%%tl"); 390 break; 391 case MISCREG_PIL: 392 ccprintf(os, "%%pil"); 393 break; 394 case MISCREG_CWP: 395 ccprintf(os, "%%cwp"); 396 break; 397 case MISCREG_GL: 398 ccprintf(os, "%%gl"); 399 break; 400 case MISCREG_HPSTATE: 401 ccprintf(os, "%%hpstate"); 402 break; 403 case MISCREG_HTSTATE: 404 ccprintf(os, "%%htstate"); 405 break; 406 case MISCREG_HINTP: 407 ccprintf(os, "%%hintp"); 408 break; 409 case MISCREG_HTBA: 410 ccprintf(os, "%%htba"); 411 break; 412 case MISCREG_HSTICK_CMPR: 413 ccprintf(os, "%%hstick_cmpr"); 414 break; 415 case MISCREG_HVER: 416 ccprintf(os, "%%hver"); 417 break; 418 case MISCREG_STRAND_STS_REG: 419 ccprintf(os, "%%strand_sts_reg"); 420 break; 421 case MISCREG_FSR: 422 ccprintf(os, "%%fsr"); 423 break; 424 default: 425 ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); 426 } 427 } 428 } 429 430 std::string SparcStaticInst::generateDisassembly(Addr pc, 431 const SymbolTable *symtab) const 432 { 433 std::stringstream ss; 434 435 printMnemonic(ss, mnemonic); 436 437 // just print the first two source regs... if there's 438 // a third one, it's a read-modify-write dest (Rc), 439 // e.g. for CMOVxx 440 if(_numSrcRegs > 0) 441 { 442 printReg(ss, _srcRegIdx[0]); 443 } 444 if(_numSrcRegs > 1) 445 { 446 ss << ","; 447 printReg(ss, _srcRegIdx[1]); 448 } 449 450 // just print the first dest... if there's a second one, 451 // it's generally implicit 452 if(_numDestRegs > 0) 453 { 454 if(_numSrcRegs > 0) 455 ss << ","; 456 printReg(ss, _destRegIdx[0]); 457 } 458 459 return ss.str(); 460 } 461 462 bool passesFpCondition(uint32_t fcc, uint32_t condition) 463 { 464 bool u = (fcc == 3); 465 bool g = (fcc == 2); 466 bool l = (fcc == 1); 467 bool e = (fcc == 0); 468 switch(condition) 469 { 470 case FAlways: 471 return 1; 472 case FNever: 473 return 0; 474 case FUnordered: 475 return u; 476 case FGreater: 477 return g; 478 case FUnorderedOrGreater: 479 return u || g; 480 case FLess: 481 return l; 482 case FUnorderedOrLess: 483 return u || l; 484 case FLessOrGreater: 485 return l || g; 486 case FNotEqual: 487 return l || g || u; 488 case FEqual: 489 return e; 490 case FUnorderedOrEqual: 491 return u || e; 492 case FGreaterOrEqual: 493 return g || e; 494 case FUnorderedOrGreaterOrEqual: 495 return u || g || e; 496 case FLessOrEqual: 497 return l || e; 498 case FUnorderedOrLessOrEqual: 499 return u || l || e; 500 case FOrdered: 501 return e || l || g; 502 } 503 panic("Tried testing condition nonexistant " 504 "condition code %d", condition); 505 } 506 507 bool passesCondition(uint32_t codes, uint32_t condition) 508 { 509 CondCodes condCodes; 510 condCodes.bits = 0; 511 condCodes.c = codes & 0x1 ? 1 : 0; 512 condCodes.v = codes & 0x2 ? 1 : 0; 513 condCodes.z = codes & 0x4 ? 1 : 0; 514 condCodes.n = codes & 0x8 ? 1 : 0; 515 516 switch(condition) 517 { 518 case Always: 519 return true; 520 case Never: 521 return false; 522 case NotEqual: 523 return !condCodes.z; 524 case Equal: 525 return condCodes.z; 526 case Greater: 527 return !(condCodes.z | (condCodes.n ^ condCodes.v)); 528 case LessOrEqual: 529 return condCodes.z | (condCodes.n ^ condCodes.v); 530 case GreaterOrEqual: 531 return !(condCodes.n ^ condCodes.v); 532 case Less: 533 return (condCodes.n ^ condCodes.v); 534 case GreaterUnsigned: 535 return !(condCodes.c | condCodes.z); 536 case LessOrEqualUnsigned: 537 return (condCodes.c | condCodes.z); 538 case CarryClear: 539 return !condCodes.c; 540 case CarrySet: 541 return condCodes.c; 542 case Positive: 543 return !condCodes.n; 544 case Negative: 545 return condCodes.n; 546 case OverflowClear: 547 return !condCodes.v; 548 case OverflowSet: 549 return condCodes.v; 550 } 551 panic("Tried testing condition nonexistant " 552 "condition code %d", condition); 553 } 554}}; 555 556output exec {{ 557 /// Check "FP enabled" machine status bit. Called when executing any FP 558 /// instruction in full-system mode. 559 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled 560 /// if not. Non-full-system mode: always returns NoFault. 561#if FULL_SYSTEM 562 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 563 { 564 Fault fault = NoFault; // dummy... this ipr access should not fault 565 if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef && 566 xc->readMiscReg(MISCREG_FPRS) & 0x4) 567 return NoFault; 568 else 569 return new FpDisabled; 570 } 571#else 572 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 573 { 574 return NoFault; 575 } 576#endif 577}}; 578 579 580