static_inst.cc revision 6306:fe1004d455b2
1/* Copyright (c) 2007-2008 The Florida State University 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: Stephen Hines 28 */ 29 30#include "arch/arm/insts/static_inst.hh" 31#include "base/condcodes.hh" 32#include "base/loader/symtab.hh" 33 34namespace ArmISA 35{ 36// Shift Rm by an immediate value 37int32_t 38ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt, 39 uint32_t type, uint32_t cfval) const 40{ 41 assert(shamt < 32); 42 ArmShiftType shiftType; 43 shiftType = (ArmShiftType)type; 44 45 switch (shiftType) 46 { 47 case LSL: 48 return base << shamt; 49 case LSR: 50 if (shamt == 0) 51 return 0; 52 else 53 return base >> shamt; 54 case ASR: 55 if (shamt == 0) 56 return (int32_t)base >> 31; 57 else 58 return (int32_t)base >> shamt; 59 case ROR: 60 if (shamt == 0) 61 return (cfval << 31) | (base >> 1); // RRX 62 else 63 return (base << (32 - shamt)) | (base >> shamt); 64 default: 65 fprintf(stderr, "Unhandled shift type\n"); 66 exit(1); 67 break; 68 } 69 return 0; 70} 71 72// Shift Rm by Rs 73int32_t 74ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt, 75 uint32_t type, uint32_t cfval) const 76{ 77 enum ArmShiftType shiftType; 78 shiftType = (enum ArmShiftType) type; 79 80 switch (shiftType) 81 { 82 case LSL: 83 if (shamt >= 32) 84 return 0; 85 else 86 return base << shamt; 87 case LSR: 88 if (shamt >= 32) 89 return 0; 90 else 91 return base >> shamt; 92 case ASR: 93 if (shamt >= 32) 94 return (int32_t)base >> 31; 95 else 96 return (int32_t)base >> shamt; 97 case ROR: 98 shamt = shamt & 0x1f; 99 if (shamt == 0) 100 return base; 101 else 102 return (base << (32 - shamt)) | (base >> shamt); 103 default: 104 fprintf(stderr, "Unhandled shift type\n"); 105 exit(1); 106 break; 107 } 108 return 0; 109} 110 111 112// Generate C for a shift by immediate 113bool 114ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt, 115 uint32_t type, uint32_t cfval) const 116{ 117 enum ArmShiftType shiftType; 118 shiftType = (enum ArmShiftType) type; 119 120 switch (shiftType) 121 { 122 case LSL: 123 if (shamt == 0) 124 return cfval; 125 else 126 return (base >> (32 - shamt)) & 1; 127 case LSR: 128 if (shamt == 0) 129 return (base >> 31); 130 else 131 return (base >> (shamt - 1)) & 1; 132 case ASR: 133 if (shamt == 0) 134 return (base >> 31); 135 else 136 return (base >> (shamt - 1)) & 1; 137 case ROR: 138 shamt = shamt & 0x1f; 139 if (shamt == 0) 140 return (base & 1); // RRX 141 else 142 return (base >> (shamt - 1)) & 1; 143 default: 144 fprintf(stderr, "Unhandled shift type\n"); 145 exit(1); 146 break; 147 } 148 return 0; 149} 150 151 152// Generate C for a shift by Rs 153bool 154ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt, 155 uint32_t type, uint32_t cfval) const 156{ 157 enum ArmShiftType shiftType; 158 shiftType = (enum ArmShiftType) type; 159 160 if (shamt == 0) 161 return cfval; 162 163 switch (shiftType) 164 { 165 case LSL: 166 if (shamt > 32) 167 return 0; 168 else 169 return (base >> (32 - shamt)) & 1; 170 case LSR: 171 if (shamt > 32) 172 return 0; 173 else 174 return (base >> (shamt - 1)) & 1; 175 case ASR: 176 if (shamt > 32) 177 shamt = 32; 178 return (base >> (shamt - 1)) & 1; 179 case ROR: 180 shamt = shamt & 0x1f; 181 if (shamt == 0) 182 shamt = 32; 183 return (base >> (shamt - 1)) & 1; 184 default: 185 fprintf(stderr, "Unhandled shift type\n"); 186 exit(1); 187 break; 188 } 189 return 0; 190} 191 192 193// Generate the appropriate carry bit for an addition operation 194bool 195ArmStaticInst::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const 196{ 197 return findCarry(32, result, lhs, rhs); 198} 199 200// Generate the appropriate carry bit for a subtraction operation 201bool 202ArmStaticInst::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const 203{ 204 return findCarry(32, result, lhs, ~rhs); 205} 206 207bool 208ArmStaticInst::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const 209{ 210 return findOverflow(32, result, lhs, rhs); 211} 212 213bool 214ArmStaticInst::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const 215{ 216 return findOverflow(32, result, lhs, ~rhs); 217} 218 219void 220ArmStaticInst::printReg(std::ostream &os, int reg) const 221{ 222 if (reg < FP_Base_DepTag) { 223 switch (reg) { 224 case PCReg: 225 ccprintf(os, "pc"); 226 break; 227 case StackPointerReg: 228 ccprintf(os, "sp"); 229 break; 230 case FramePointerReg: 231 ccprintf(os, "fp"); 232 break; 233 case ReturnAddressReg: 234 ccprintf(os, "lr"); 235 break; 236 default: 237 ccprintf(os, "r%d", reg); 238 break; 239 } 240 } else if (reg < Ctrl_Base_DepTag) { 241 ccprintf(os, "f%d", reg - FP_Base_DepTag); 242 } else { 243 reg -= Ctrl_Base_DepTag; 244 assert(reg < NUM_MISCREGS); 245 ccprintf(os, "%s", ArmISA::miscRegName[reg]); 246 } 247} 248 249void 250ArmStaticInst::printMnemonic(std::ostream &os, 251 const std::string &suffix, 252 bool withPred) const 253{ 254 os << " " << mnemonic; 255 if (withPred) { 256 unsigned condCode = machInst.condCode; 257 switch (condCode) { 258 case COND_EQ: 259 os << "eq"; 260 break; 261 case COND_NE: 262 os << "ne"; 263 break; 264 case COND_CS: 265 os << "cs"; 266 break; 267 case COND_CC: 268 os << "cc"; 269 break; 270 case COND_MI: 271 os << "mi"; 272 break; 273 case COND_PL: 274 os << "pl"; 275 break; 276 case COND_VS: 277 os << "vs"; 278 break; 279 case COND_VC: 280 os << "vc"; 281 break; 282 case COND_HI: 283 os << "hi"; 284 break; 285 case COND_LS: 286 os << "ls"; 287 break; 288 case COND_GE: 289 os << "ge"; 290 break; 291 case COND_LT: 292 os << "lt"; 293 break; 294 case COND_GT: 295 os << "gt"; 296 break; 297 case COND_LE: 298 os << "le"; 299 break; 300 case COND_AL: 301 // This one is implicit. 302 break; 303 case COND_NV: 304 os << "nv"; 305 break; 306 default: 307 panic("Unrecognized condition code %d.\n", condCode); 308 } 309 os << suffix << " "; 310 } 311} 312 313void 314ArmStaticInst::printMemSymbol(std::ostream &os, 315 const SymbolTable *symtab, 316 const std::string &prefix, 317 const Addr addr, 318 const std::string &suffix) const 319{ 320 Addr symbolAddr; 321 std::string symbol; 322 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) { 323 ccprintf(os, "%s%s", prefix, symbol); 324 if (symbolAddr != addr) 325 ccprintf(os, "+%d", addr - symbolAddr); 326 ccprintf(os, suffix); 327 } 328} 329 330void 331ArmStaticInst::printShiftOperand(std::ostream &os) const 332{ 333 printReg(os, machInst.rm); 334 335 bool immShift = (machInst.opcode4 == 0); 336 bool done = false; 337 unsigned shiftAmt = (machInst.shiftSize); 338 ArmShiftType type = (ArmShiftType)(uint32_t)machInst.shift; 339 340 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0) 341 shiftAmt = 32; 342 343 switch (type) { 344 case LSL: 345 if (immShift && shiftAmt == 0) { 346 done = true; 347 break; 348 } 349 os << ", LSL"; 350 break; 351 case LSR: 352 os << ", LSR"; 353 break; 354 case ASR: 355 os << ", ASR"; 356 break; 357 case ROR: 358 if (immShift && shiftAmt == 0) { 359 os << ", RRX"; 360 done = true; 361 break; 362 } 363 os << ", ROR"; 364 break; 365 default: 366 panic("Tried to disassemble unrecognized shift type.\n"); 367 } 368 if (!done) { 369 os << " "; 370 if (immShift) 371 os << "#" << shiftAmt; 372 else 373 printReg(os, machInst.rs); 374 } 375} 376 377void 378ArmStaticInst::printDataInst(std::ostream &os, bool withImm) const 379{ 380 printMnemonic(os, machInst.sField ? "s" : ""); 381 //XXX It would be nice if the decoder figured this all out for us. 382 unsigned opcode = machInst.opcode; 383 bool firstOp = true; 384 385 // Destination 386 // Cmp, cmn, teq, and tst don't have one. 387 if (opcode < 8 || opcode > 0xb) { 388 firstOp = false; 389 printReg(os, machInst.rd); 390 } 391 392 // Source 1. 393 // Mov and Movn don't have one of these. 394 if (opcode != 0xd && opcode != 0xf) { 395 if (!firstOp) 396 os << ", "; 397 firstOp = false; 398 printReg(os, machInst.rn); 399 } 400 401 if (!firstOp) 402 os << ", "; 403 if (withImm) { 404 unsigned rotate = machInst.rotate * 2; 405 uint32_t imm = machInst.imm; 406 ccprintf(os, "#%#x", (imm << (32 - rotate)) | (imm >> rotate)); 407 } else { 408 printShiftOperand(os); 409 } 410} 411 412std::string 413ArmStaticInst::generateDisassembly(Addr pc, 414 const SymbolTable *symtab) const 415{ 416 std::stringstream ss; 417 printMnemonic(ss); 418 return ss.str(); 419} 420} 421