base.isa revision 4004
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 157let {{ 158 def splitOutImm(code): 159 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?') 160 rOrImmMatch = matcher.search(code) 161 if (rOrImmMatch == None): 162 return (False, code, '', '', '') 163 rString = rOrImmMatch.group("rNum") 164 if (rOrImmMatch.group("typeQual") != None): 165 rString += rOrImmMatch.group("typeQual") 166 iString = rOrImmMatch.group("iNum") 167 orig_code = code 168 code = matcher.sub('Rs' + rString, orig_code) 169 imm_code = matcher.sub('imm', orig_code) 170 return (True, code, imm_code, rString, iString) 171}}; 172 173output decoder {{ 174 175 inline void printMnemonic(std::ostream &os, const char * mnemonic) 176 { 177 ccprintf(os, "\t%s ", mnemonic); 178 } 179 180 void SparcStaticInst::printRegArray(std::ostream &os, 181 const RegIndex indexArray[], int num) const 182 { 183 if(num <= 0) 184 return; 185 printReg(os, indexArray[0]); 186 for(int x = 1; x < num; x++) 187 { 188 os << ", "; 189 printReg(os, indexArray[x]); 190 } 191 } 192 193 void 194 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const 195 { 196 if(_numSrcRegs > reg) 197 printReg(os, _srcRegIdx[reg]); 198 } 199 200 void 201 SparcStaticInst::printDestReg(std::ostream &os, int reg) const 202 { 203 if(_numDestRegs > reg) 204 printReg(os, _destRegIdx[reg]); 205 } 206 207 void 208 SparcStaticInst::printReg(std::ostream &os, int reg) const 209 { 210 const int MaxGlobal = 8; 211 const int MaxOutput = 16; 212 const int MaxLocal = 24; 213 const int MaxInput = 32; 214 const int MaxMicroReg = 40; 215 if (reg < FP_Base_DepTag) { 216 //If we used a register from the next or previous window, 217 //take out the offset. 218 while (reg >= MaxMicroReg) 219 reg -= MaxMicroReg; 220 if (reg == FramePointerReg) 221 ccprintf(os, "%%fp"); 222 else if (reg == StackPointerReg) 223 ccprintf(os, "%%sp"); 224 else if(reg < MaxGlobal) 225 ccprintf(os, "%%g%d", reg); 226 else if(reg < MaxOutput) 227 ccprintf(os, "%%o%d", reg - MaxGlobal); 228 else if(reg < MaxLocal) 229 ccprintf(os, "%%l%d", reg - MaxOutput); 230 else if(reg < MaxInput) 231 ccprintf(os, "%%i%d", reg - MaxLocal); 232 else if(reg < MaxMicroReg) 233 ccprintf(os, "%%u%d", reg - MaxInput); 234 //The fake int regs that are really control regs 235 else { 236 switch (reg - MaxMicroReg) { 237 case 1: 238 ccprintf(os, "%%y"); 239 break; 240 case 2: 241 ccprintf(os, "%%ccr"); 242 break; 243 case 3: 244 ccprintf(os, "%%cansave"); 245 break; 246 case 4: 247 ccprintf(os, "%%canrestore"); 248 break; 249 case 5: 250 ccprintf(os, "%%cleanwin"); 251 break; 252 case 6: 253 ccprintf(os, "%%otherwin"); 254 break; 255 case 7: 256 ccprintf(os, "%%wstate"); 257 break; 258 } 259 } 260 } else if (reg < Ctrl_Base_DepTag) { 261 ccprintf(os, "%%f%d", reg - FP_Base_DepTag); 262 } else { 263 switch (reg - Ctrl_Base_DepTag) { 264 case MISCREG_ASI: 265 ccprintf(os, "%%asi"); 266 break; 267 case MISCREG_FPRS: 268 ccprintf(os, "%%fprs"); 269 break; 270 case MISCREG_PCR: 271 ccprintf(os, "%%pcr"); 272 break; 273 case MISCREG_PIC: 274 ccprintf(os, "%%pic"); 275 break; 276 case MISCREG_GSR: 277 ccprintf(os, "%%gsr"); 278 break; 279 case MISCREG_SOFTINT: 280 ccprintf(os, "%%softint"); 281 break; 282 case MISCREG_SOFTINT_SET: 283 ccprintf(os, "%%softint_set"); 284 break; 285 case MISCREG_SOFTINT_CLR: 286 ccprintf(os, "%%softint_clr"); 287 break; 288 case MISCREG_TICK_CMPR: 289 ccprintf(os, "%%tick_cmpr"); 290 break; 291 case MISCREG_STICK: 292 ccprintf(os, "%%stick"); 293 break; 294 case MISCREG_STICK_CMPR: 295 ccprintf(os, "%%stick_cmpr"); 296 break; 297 case MISCREG_TPC: 298 ccprintf(os, "%%tpc"); 299 break; 300 case MISCREG_TNPC: 301 ccprintf(os, "%%tnpc"); 302 break; 303 case MISCREG_TSTATE: 304 ccprintf(os, "%%tstate"); 305 break; 306 case MISCREG_TT: 307 ccprintf(os, "%%tt"); 308 break; 309 case MISCREG_TICK: 310 ccprintf(os, "%%tick"); 311 break; 312 case MISCREG_TBA: 313 ccprintf(os, "%%tba"); 314 break; 315 case MISCREG_PSTATE: 316 ccprintf(os, "%%pstate"); 317 break; 318 case MISCREG_TL: 319 ccprintf(os, "%%tl"); 320 break; 321 case MISCREG_PIL: 322 ccprintf(os, "%%pil"); 323 break; 324 case MISCREG_CWP: 325 ccprintf(os, "%%cwp"); 326 break; 327 case MISCREG_GL: 328 ccprintf(os, "%%gl"); 329 break; 330 case MISCREG_HPSTATE: 331 ccprintf(os, "%%hpstate"); 332 break; 333 case MISCREG_HTSTATE: 334 ccprintf(os, "%%htstate"); 335 break; 336 case MISCREG_HINTP: 337 ccprintf(os, "%%hintp"); 338 break; 339 case MISCREG_HTBA: 340 ccprintf(os, "%%htba"); 341 break; 342 case MISCREG_HSTICK_CMPR: 343 ccprintf(os, "%%hstick_cmpr"); 344 break; 345 case MISCREG_HVER: 346 ccprintf(os, "%%hver"); 347 break; 348 case MISCREG_STRAND_STS_REG: 349 ccprintf(os, "%%strand_sts_reg"); 350 break; 351 case MISCREG_FSR: 352 ccprintf(os, "%%fsr"); 353 break; 354 default: 355 ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); 356 } 357 } 358 } 359 360 std::string SparcStaticInst::generateDisassembly(Addr pc, 361 const SymbolTable *symtab) const 362 { 363 std::stringstream ss; 364 365 printMnemonic(ss, mnemonic); 366 367 // just print the first two source regs... if there's 368 // a third one, it's a read-modify-write dest (Rc), 369 // e.g. for CMOVxx 370 if(_numSrcRegs > 0) 371 { 372 printReg(ss, _srcRegIdx[0]); 373 } 374 if(_numSrcRegs > 1) 375 { 376 ss << ","; 377 printReg(ss, _srcRegIdx[1]); 378 } 379 380 // just print the first dest... if there's a second one, 381 // it's generally implicit 382 if(_numDestRegs > 0) 383 { 384 if(_numSrcRegs > 0) 385 ss << ","; 386 printReg(ss, _destRegIdx[0]); 387 } 388 389 return ss.str(); 390 } 391 392 bool passesFpCondition(uint32_t fcc, uint32_t condition) 393 { 394 bool u = (fcc == 3); 395 bool g = (fcc == 2); 396 bool l = (fcc == 1); 397 bool e = (fcc == 0); 398 switch(condition) 399 { 400 case FAlways: 401 return 1; 402 case FNever: 403 return 0; 404 case FUnordered: 405 return u; 406 case FGreater: 407 return g; 408 case FUnorderedOrGreater: 409 return u || g; 410 case FLess: 411 return l; 412 case FUnorderedOrLess: 413 return u || l; 414 case FLessOrGreater: 415 return l || g; 416 case FNotEqual: 417 return l || g || u; 418 case FEqual: 419 return e; 420 case FUnorderedOrEqual: 421 return u || e; 422 case FGreaterOrEqual: 423 return g || e; 424 case FUnorderedOrGreaterOrEqual: 425 return u || g || e; 426 case FLessOrEqual: 427 return l || e; 428 case FUnorderedOrLessOrEqual: 429 return u || l || e; 430 case FOrdered: 431 return e || l || g; 432 } 433 panic("Tried testing condition nonexistant " 434 "condition code %d", condition); 435 } 436 437 bool passesCondition(uint32_t codes, uint32_t condition) 438 { 439 CondCodes condCodes; 440 condCodes.bits = 0; 441 condCodes.c = codes & 0x1 ? 1 : 0; 442 condCodes.v = codes & 0x2 ? 1 : 0; 443 condCodes.z = codes & 0x4 ? 1 : 0; 444 condCodes.n = codes & 0x8 ? 1 : 0; 445 446 switch(condition) 447 { 448 case Always: 449 return true; 450 case Never: 451 return false; 452 case NotEqual: 453 return !condCodes.z; 454 case Equal: 455 return condCodes.z; 456 case Greater: 457 return !(condCodes.z | (condCodes.n ^ condCodes.v)); 458 case LessOrEqual: 459 return condCodes.z | (condCodes.n ^ condCodes.v); 460 case GreaterOrEqual: 461 return !(condCodes.n ^ condCodes.v); 462 case Less: 463 return (condCodes.n ^ condCodes.v); 464 case GreaterUnsigned: 465 return !(condCodes.c | condCodes.z); 466 case LessOrEqualUnsigned: 467 return (condCodes.c | condCodes.z); 468 case CarryClear: 469 return !condCodes.c; 470 case CarrySet: 471 return condCodes.c; 472 case Positive: 473 return !condCodes.n; 474 case Negative: 475 return condCodes.n; 476 case OverflowClear: 477 return !condCodes.v; 478 case OverflowSet: 479 return condCodes.v; 480 } 481 panic("Tried testing condition nonexistant " 482 "condition code %d", condition); 483 } 484}}; 485 486output exec {{ 487 /// Check "FP enabled" machine status bit. Called when executing any FP 488 /// instruction in full-system mode. 489 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled 490 /// if not. Non-full-system mode: always returns NoFault. 491#if FULL_SYSTEM 492 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 493 { 494 Fault fault = NoFault; // dummy... this ipr access should not fault 495 if (xc->readMiscRegWithEffect(MISCREG_PSTATE) & PSTATE::pef && 496 xc->readMiscRegWithEffect(MISCREG_FPRS) & 0x4) 497 return NoFault; 498 else 499 return new FpDisabled; 500 } 501#else 502 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) 503 { 504 return NoFault; 505 } 506#endif 507}}; 508 509 510