1/* 2 * Copyright (c) 2006-2007 The Regents of The University of Michigan 3 * All rights reserved 4 * Copyright 2017 Google Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Gabe Black 30 */ 31 32#include "arch/sparc/insts/static_inst.hh" 33 34namespace SparcISA 35{ 36 37const char *CondTestAbbrev[] = 38{ 39 [Never] = "nev", 40 [Equal] = "e", 41 [LessOrEqual] = "le", 42 [Less] = "l", 43 [LessOrEqualUnsigned] = "leu", 44 [CarrySet] = "c", 45 [Negative] = "n", 46 [OverflowSet] = "o", 47 [Always] = "a", 48 [NotEqual] = "ne", 49 [Greater] = "g", 50 [GreaterOrEqual] = "ge", 51 [GreaterUnsigned] = "gu", 52 [CarryClear] = "cc", 53 [Positive] = "p", 54 [OverflowClear] = "oc" 55}; 56 57void 58SparcStaticInst::printMnemonic(std::ostream &os, const char *mnemonic) 59{ 60 ccprintf(os, "\t%s ", mnemonic); 61} 62 63void 64SparcStaticInst::printRegArray(std::ostream &os, const RegId indexArray[], 65 int num) const 66{ 67 if (num <= 0) 68 return; 69 printReg(os, indexArray[0]); 70 for (int x = 1; x < num; x++) { 71 os << ", "; 72 printReg(os, indexArray[x]); 73 } 74} 75 76void 77SparcStaticInst::advancePC(SparcISA::PCState &pcState) const 78{ 79 pcState.advance(); 80} 81 82void 83SparcStaticInst::printSrcReg(std::ostream &os, int reg) const 84{ 85 if (_numSrcRegs > reg) 86 printReg(os, _srcRegIdx[reg]); 87} 88 89void 90SparcStaticInst::printDestReg(std::ostream &os, int reg) const 91{ 92 if (_numDestRegs > reg) 93 printReg(os, _destRegIdx[reg]); 94} 95 96void 97SparcStaticInst::printReg(std::ostream &os, RegId reg) 98{ 99 const int MaxGlobal = 8; 100 const int MaxOutput = 16; 101 const int MaxLocal = 24; 102 const int MaxInput = 32; 103 const int MaxMicroReg = 40; 104 RegIndex reg_idx = reg.index(); 105 if (reg.isIntReg()) { 106 // If we used a register from the next or previous window, 107 // take out the offset. 108 while (reg_idx >= MaxMicroReg) 109 reg_idx -= MaxMicroReg; 110 if (reg_idx == FramePointerReg) 111 ccprintf(os, "%%fp"); 112 else if (reg_idx == StackPointerReg) 113 ccprintf(os, "%%sp"); 114 else if (reg_idx < MaxGlobal) 115 ccprintf(os, "%%g%d", reg_idx); 116 else if (reg_idx < MaxOutput) 117 ccprintf(os, "%%o%d", reg_idx - MaxGlobal); 118 else if (reg_idx < MaxLocal) 119 ccprintf(os, "%%l%d", reg_idx - MaxOutput); 120 else if (reg_idx < MaxInput) 121 ccprintf(os, "%%i%d", reg_idx - MaxLocal); 122 else if (reg_idx < MaxMicroReg) 123 ccprintf(os, "%%u%d", reg_idx - MaxInput); 124 // The fake int regs that are really control regs 125 else { 126 switch (reg_idx - MaxMicroReg) { 127 case 1: 128 ccprintf(os, "%%y"); 129 break; 130 case 2: 131 ccprintf(os, "%%ccr"); 132 break; 133 case 3: 134 ccprintf(os, "%%cansave"); 135 break; 136 case 4: 137 ccprintf(os, "%%canrestore"); 138 break; 139 case 5: 140 ccprintf(os, "%%cleanwin"); 141 break; 142 case 6: 143 ccprintf(os, "%%otherwin"); 144 break; 145 case 7: 146 ccprintf(os, "%%wstate"); 147 break; 148 } 149 } 150 } else if (reg.isFloatReg()) { 151 ccprintf(os, "%%f%d", reg_idx); 152 } else { 153 switch (reg_idx) { 154 case MISCREG_ASI: 155 ccprintf(os, "%%asi"); 156 break; 157 case MISCREG_FPRS: 158 ccprintf(os, "%%fprs"); 159 break; 160 case MISCREG_PCR: 161 ccprintf(os, "%%pcr"); 162 break; 163 case MISCREG_PIC: 164 ccprintf(os, "%%pic"); 165 break; 166 case MISCREG_GSR: 167 ccprintf(os, "%%gsr"); 168 break; 169 case MISCREG_SOFTINT: 170 ccprintf(os, "%%softint"); 171 break; 172 case MISCREG_SOFTINT_SET: 173 ccprintf(os, "%%softint_set"); 174 break; 175 case MISCREG_SOFTINT_CLR: 176 ccprintf(os, "%%softint_clr"); 177 break; 178 case MISCREG_TICK_CMPR: 179 ccprintf(os, "%%tick_cmpr"); 180 break; 181 case MISCREG_STICK: 182 ccprintf(os, "%%stick"); 183 break; 184 case MISCREG_STICK_CMPR: 185 ccprintf(os, "%%stick_cmpr"); 186 break; 187 case MISCREG_TPC: 188 ccprintf(os, "%%tpc"); 189 break; 190 case MISCREG_TNPC: 191 ccprintf(os, "%%tnpc"); 192 break; 193 case MISCREG_TSTATE: 194 ccprintf(os, "%%tstate"); 195 break; 196 case MISCREG_TT: 197 ccprintf(os, "%%tt"); 198 break; 199 case MISCREG_TICK: 200 ccprintf(os, "%%tick"); 201 break; 202 case MISCREG_TBA: 203 ccprintf(os, "%%tba"); 204 break; 205 case MISCREG_PSTATE: 206 ccprintf(os, "%%pstate"); 207 break; 208 case MISCREG_TL: 209 ccprintf(os, "%%tl"); 210 break; 211 case MISCREG_PIL: 212 ccprintf(os, "%%pil"); 213 break; 214 case MISCREG_CWP: 215 ccprintf(os, "%%cwp"); 216 break; 217 case MISCREG_GL: 218 ccprintf(os, "%%gl"); 219 break; 220 case MISCREG_HPSTATE: 221 ccprintf(os, "%%hpstate"); 222 break; 223 case MISCREG_HTSTATE: 224 ccprintf(os, "%%htstate"); 225 break; 226 case MISCREG_HINTP: 227 ccprintf(os, "%%hintp"); 228 break; 229 case MISCREG_HTBA: 230 ccprintf(os, "%%htba"); 231 break; 232 case MISCREG_HSTICK_CMPR: 233 ccprintf(os, "%%hstick_cmpr"); 234 break; 235 case MISCREG_HVER: 236 ccprintf(os, "%%hver"); 237 break; 238 case MISCREG_STRAND_STS_REG: 239 ccprintf(os, "%%strand_sts_reg"); 240 break; 241 case MISCREG_FSR: 242 ccprintf(os, "%%fsr"); 243 break; 244 default: 245 ccprintf(os, "%%ctrl%d", reg_idx); 246 } 247 } 248} 249 250std::string 251SparcStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const 252{ 253 std::stringstream ss; 254 255 printMnemonic(ss, mnemonic); 256 257 // just print the first two source regs... if there's 258 // a third one, it's a read-modify-write dest (Rc), 259 // e.g. for CMOVxx 260 if (_numSrcRegs > 0) 261 printReg(ss, _srcRegIdx[0]); 262 if (_numSrcRegs > 1) { 263 ss << ","; 264 printReg(ss, _srcRegIdx[1]); 265 } 266 267 // just print the first dest... if there's a second one, 268 // it's generally implicit 269 if (_numDestRegs > 0) { 270 if (_numSrcRegs > 0) 271 ss << ","; 272 printReg(ss, _destRegIdx[0]); 273 } 274 275 return ss.str(); 276} 277 278bool 279SparcStaticInst::passesFpCondition(uint32_t fcc, uint32_t condition) 280{ 281 bool u = (fcc == 3); 282 bool g = (fcc == 2); 283 bool l = (fcc == 1); 284 bool e = (fcc == 0); 285 286 switch (condition) { 287 case FAlways: 288 return 1; 289 case FNever: 290 return 0; 291 case FUnordered: 292 return u; 293 case FGreater: 294 return g; 295 case FUnorderedOrGreater: 296 return u || g; 297 case FLess: 298 return l; 299 case FUnorderedOrLess: 300 return u || l; 301 case FLessOrGreater: 302 return l || g; 303 case FNotEqual: 304 return l || g || u; 305 case FEqual: 306 return e; 307 case FUnorderedOrEqual: 308 return u || e; 309 case FGreaterOrEqual: 310 return g || e; 311 case FUnorderedOrGreaterOrEqual: 312 return u || g || e; 313 case FLessOrEqual: 314 return l || e; 315 case FUnorderedOrLessOrEqual: 316 return u || l || e; 317 case FOrdered: 318 return e || l || g; 319 } 320 panic("Tried testing condition nonexistant condition code %d", condition); 321} 322 323bool 324SparcStaticInst::passesCondition(uint32_t codes, uint32_t condition) 325{ 326 BitUnion32(CondCodes) 327 Bitfield<0> c; 328 Bitfield<1> v; 329 Bitfield<2> z; 330 Bitfield<3> n; 331 EndBitUnion(CondCodes) 332 CondCodes condCodes = codes; 333 334 switch (condition) { 335 case Always: 336 return true; 337 case Never: 338 return false; 339 case NotEqual: 340 return !condCodes.z; 341 case Equal: 342 return condCodes.z; 343 case Greater: 344 return !(condCodes.z | (condCodes.n ^ condCodes.v)); 345 case LessOrEqual: 346 return condCodes.z | (condCodes.n ^ condCodes.v); 347 case GreaterOrEqual: 348 return !(condCodes.n ^ condCodes.v); 349 case Less: 350 return (condCodes.n ^ condCodes.v); 351 case GreaterUnsigned: 352 return !(condCodes.c | condCodes.z); 353 case LessOrEqualUnsigned: 354 return (condCodes.c | condCodes.z); 355 case CarryClear: 356 return !condCodes.c; 357 case CarrySet: 358 return condCodes.c; 359 case Positive: 360 return !condCodes.n; 361 case Negative: 362 return condCodes.n; 363 case OverflowClear: 364 return !condCodes.v; 365 case OverflowSet: 366 return condCodes.v; 367 } 368 panic("Tried testing condition nonexistant " 369 "condition code %d", condition); 370} 371 372} 373