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