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