base.isa revision 3978:739bc3a17929
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 extern char * CondTestAbbrev[]; 71 72 /** 73 * Base class for all SPARC static instructions. 74 */ 75 class SparcStaticInst : public StaticInst 76 { 77 protected: 78 // Constructor. 79 SparcStaticInst(const char *mnem, 80 ExtMachInst _machInst, OpClass __opClass) 81 : StaticInst(mnem, _machInst, __opClass) 82 { 83 } 84 85 std::string generateDisassembly(Addr pc, 86 const SymbolTable *symtab) const; 87 88 void printReg(std::ostream &os, int reg) const; 89 void printSrcReg(std::ostream &os, int reg) const; 90 void printDestReg(std::ostream &os, int reg) const; 91 92 void printRegArray(std::ostream &os, 93 const RegIndex indexArray[], int num) const; 94 }; 95 96 bool passesCondition(uint32_t codes, uint32_t condition); 97 98 inline int64_t sign_ext(uint64_t data, int origWidth) 99 { 100 int shiftAmount = 64 - origWidth; 101 return (((int64_t)data) << shiftAmount) >> shiftAmount; 102 } 103}}; 104 105output decoder {{ 106 107 char * CondTestAbbrev[] = 108 { 109 "nev", //Never 110 "e", //Equal 111 "le", //Less or Equal 112 "l", //Less 113 "leu", //Less or Equal Unsigned 114 "c", //Carry set 115 "n", //Negative 116 "o", //Overflow set 117 "a", //Always 118 "ne", //Not Equal 119 "g", //Greater 120 "ge", //Greater or Equal 121 "gu", //Greater Unsigned 122 "cc", //Carry clear 123 "p", //Positive 124 "oc" //Overflow Clear 125 }; 126}}; 127 128def template ROrImmDecode {{ 129 { 130 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) 131 : (SparcStaticInst *)(new %(class_name)s(machInst))); 132 } 133}}; 134 135let {{ 136 def splitOutImm(code): 137 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?') 138 rOrImmMatch = matcher.search(code) 139 if (rOrImmMatch == None): 140 return (False, code, '', '', '') 141 rString = rOrImmMatch.group("rNum") 142 if (rOrImmMatch.group("typeQual") != None): 143 rString += rOrImmMatch.group("typeQual") 144 iString = rOrImmMatch.group("iNum") 145 orig_code = code 146 code = matcher.sub('Rs' + rString, orig_code) 147 imm_code = matcher.sub('imm', orig_code) 148 return (True, code, imm_code, rString, iString) 149}}; 150 151output decoder {{ 152 153 inline void printMnemonic(std::ostream &os, const char * mnemonic) 154 { 155 ccprintf(os, "\t%s ", mnemonic); 156 } 157 158 void SparcStaticInst::printRegArray(std::ostream &os, 159 const RegIndex indexArray[], int num) const 160 { 161 if(num <= 0) 162 return; 163 printReg(os, indexArray[0]); 164 for(int x = 1; x < num; x++) 165 { 166 os << ", "; 167 printReg(os, indexArray[x]); 168 } 169 } 170 171 void 172 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const 173 { 174 if(_numSrcRegs > reg) 175 printReg(os, _srcRegIdx[reg]); 176 } 177 178 void 179 SparcStaticInst::printDestReg(std::ostream &os, int reg) const 180 { 181 if(_numDestRegs > reg) 182 printReg(os, _destRegIdx[reg]); 183 } 184 185 void 186 SparcStaticInst::printReg(std::ostream &os, int reg) const 187 { 188 const int MaxGlobal = 8; 189 const int MaxOutput = 16; 190 const int MaxLocal = 24; 191 const int MaxInput = 32; 192 const int MaxMicroReg = 40; 193 if (reg < FP_Base_DepTag) { 194 //If we used a register from the next or previous window, 195 //take out the offset. 196 while (reg >= MaxMicroReg) 197 reg -= MaxMicroReg; 198 if (reg == FramePointerReg) 199 ccprintf(os, "%%fp"); 200 else if (reg == StackPointerReg) 201 ccprintf(os, "%%sp"); 202 else if(reg < MaxGlobal) 203 ccprintf(os, "%%g%d", reg); 204 else if(reg < MaxOutput) 205 ccprintf(os, "%%o%d", reg - MaxGlobal); 206 else if(reg < MaxLocal) 207 ccprintf(os, "%%l%d", reg - MaxOutput); 208 else if(reg < MaxInput) 209 ccprintf(os, "%%i%d", reg - MaxLocal); 210 else if(reg < MaxMicroReg) 211 ccprintf(os, "%%u%d", reg - MaxInput); 212 //The fake int regs that are really control regs 213 else { 214 switch (reg - MaxMicroReg) { 215 case 1: 216 ccprintf(os, "%%y"); 217 break; 218 case 2: 219 ccprintf(os, "%%ccr"); 220 break; 221 case 3: 222 ccprintf(os, "%%cansave"); 223 break; 224 case 4: 225 ccprintf(os, "%%canrestore"); 226 break; 227 case 5: 228 ccprintf(os, "%%cleanwin"); 229 break; 230 case 6: 231 ccprintf(os, "%%otherwin"); 232 break; 233 case 7: 234 ccprintf(os, "%%wstate"); 235 break; 236 } 237 } 238 } else if (reg < Ctrl_Base_DepTag) { 239 ccprintf(os, "%%f%d", reg - FP_Base_DepTag); 240 } else { 241 switch (reg - Ctrl_Base_DepTag) { 242 case MISCREG_ASI: 243 ccprintf(os, "%%asi"); 244 break; 245 case MISCREG_FPRS: 246 ccprintf(os, "%%fprs"); 247 break; 248 case MISCREG_PCR: 249 ccprintf(os, "%%pcr"); 250 break; 251 case MISCREG_PIC: 252 ccprintf(os, "%%pic"); 253 break; 254 case MISCREG_GSR: 255 ccprintf(os, "%%gsr"); 256 break; 257 case MISCREG_SOFTINT: 258 ccprintf(os, "%%softint"); 259 break; 260 case MISCREG_SOFTINT_SET: 261 ccprintf(os, "%%softint_set"); 262 break; 263 case MISCREG_SOFTINT_CLR: 264 ccprintf(os, "%%softint_clr"); 265 break; 266 case MISCREG_TICK_CMPR: 267 ccprintf(os, "%%tick_cmpr"); 268 break; 269 case MISCREG_STICK: 270 ccprintf(os, "%%stick"); 271 break; 272 case MISCREG_STICK_CMPR: 273 ccprintf(os, "%%stick_cmpr"); 274 break; 275 case MISCREG_TPC: 276 ccprintf(os, "%%tpc"); 277 break; 278 case MISCREG_TNPC: 279 ccprintf(os, "%%tnpc"); 280 break; 281 case MISCREG_TSTATE: 282 ccprintf(os, "%%tstate"); 283 break; 284 case MISCREG_TT: 285 ccprintf(os, "%%tt"); 286 break; 287 case MISCREG_TICK: 288 ccprintf(os, "%%tick"); 289 break; 290 case MISCREG_TBA: 291 ccprintf(os, "%%tba"); 292 break; 293 case MISCREG_PSTATE: 294 ccprintf(os, "%%pstate"); 295 break; 296 case MISCREG_TL: 297 ccprintf(os, "%%tl"); 298 break; 299 case MISCREG_PIL: 300 ccprintf(os, "%%pil"); 301 break; 302 case MISCREG_CWP: 303 ccprintf(os, "%%cwp"); 304 break; 305 case MISCREG_GL: 306 ccprintf(os, "%%gl"); 307 break; 308 case MISCREG_HPSTATE: 309 ccprintf(os, "%%hpstate"); 310 break; 311 case MISCREG_HTSTATE: 312 ccprintf(os, "%%htstate"); 313 break; 314 case MISCREG_HINTP: 315 ccprintf(os, "%%hintp"); 316 break; 317 case MISCREG_HTBA: 318 ccprintf(os, "%%htba"); 319 break; 320 case MISCREG_HSTICK_CMPR: 321 ccprintf(os, "%%hstick_cmpr"); 322 break; 323 case MISCREG_HVER: 324 ccprintf(os, "%%hver"); 325 break; 326 case MISCREG_STRAND_STS_REG: 327 ccprintf(os, "%%strand_sts_reg"); 328 break; 329 case MISCREG_FSR: 330 ccprintf(os, "%%fsr"); 331 break; 332 default: 333 ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); 334 } 335 } 336 } 337 338 std::string SparcStaticInst::generateDisassembly(Addr pc, 339 const SymbolTable *symtab) const 340 { 341 std::stringstream ss; 342 343 printMnemonic(ss, mnemonic); 344 345 // just print the first two source regs... if there's 346 // a third one, it's a read-modify-write dest (Rc), 347 // e.g. for CMOVxx 348 if(_numSrcRegs > 0) 349 { 350 printReg(ss, _srcRegIdx[0]); 351 } 352 if(_numSrcRegs > 1) 353 { 354 ss << ","; 355 printReg(ss, _srcRegIdx[1]); 356 } 357 358 // just print the first dest... if there's a second one, 359 // it's generally implicit 360 if(_numDestRegs > 0) 361 { 362 if(_numSrcRegs > 0) 363 ss << ","; 364 printReg(ss, _destRegIdx[0]); 365 } 366 367 return ss.str(); 368 } 369 370 bool passesCondition(uint32_t codes, uint32_t condition) 371 { 372 CondCodes condCodes; 373 condCodes.bits = 0; 374 condCodes.c = codes & 0x1 ? 1 : 0; 375 condCodes.v = codes & 0x2 ? 1 : 0; 376 condCodes.z = codes & 0x4 ? 1 : 0; 377 condCodes.n = codes & 0x8 ? 1 : 0; 378 379 switch(condition) 380 { 381 case Always: 382 return true; 383 case Never: 384 return false; 385 case NotEqual: 386 return !condCodes.z; 387 case Equal: 388 return condCodes.z; 389 case Greater: 390 return !(condCodes.z | (condCodes.n ^ condCodes.v)); 391 case LessOrEqual: 392 return condCodes.z | (condCodes.n ^ condCodes.v); 393 case GreaterOrEqual: 394 return !(condCodes.n ^ condCodes.v); 395 case Less: 396 return (condCodes.n ^ condCodes.v); 397 case GreaterUnsigned: 398 return !(condCodes.c | condCodes.z); 399 case LessOrEqualUnsigned: 400 return (condCodes.c | condCodes.z); 401 case CarryClear: 402 return !condCodes.c; 403 case CarrySet: 404 return condCodes.c; 405 case Positive: 406 return !condCodes.n; 407 case Negative: 408 return condCodes.n; 409 case OverflowClear: 410 return !condCodes.v; 411 case OverflowSet: 412 return condCodes.v; 413 } 414 panic("Tried testing condition nonexistant " 415 "condition code %d", condition); 416 } 417}}; 418 419