macromem.cc revision 8196:e46d051c35be
1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2007-2008 The Florida State University 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Stephen Hines 41 */ 42 43#include "arch/arm/insts/macromem.hh" 44#include "arch/arm/decoder.hh" 45#include <sstream> 46 47using namespace std; 48using namespace ArmISAInst; 49 50namespace ArmISA 51{ 52 53MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst, 54 OpClass __opClass, IntRegIndex rn, 55 bool index, bool up, bool user, bool writeback, 56 bool load, uint32_t reglist) : 57 PredMacroOp(mnem, machInst, __opClass) 58{ 59 uint32_t regs = reglist; 60 uint32_t ones = number_of_ones(reglist); 61 // Remember that writeback adds a uop or two and the temp register adds one 62 numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1; 63 64 // It's technically legal to do a lot of nothing 65 if (!ones) 66 numMicroops = 1; 67 68 microOps = new StaticInstPtr[numMicroops]; 69 uint32_t addr = 0; 70 71 if (!up) 72 addr = (ones << 2) - 4; 73 74 if (!index) 75 addr += 4; 76 77 StaticInstPtr *uop = microOps; 78 79 // Add 0 to Rn and stick it in ureg0. 80 // This is equivalent to a move. 81 *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0); 82 83 unsigned reg = 0; 84 unsigned regIdx = 0; 85 bool force_user = user & !bits(reglist, 15); 86 bool exception_ret = user & bits(reglist, 15); 87 88 for (int i = 0; i < ones; i++) { 89 // Find the next register. 90 while (!bits(regs, reg)) 91 reg++; 92 replaceBits(regs, reg, 0); 93 94 regIdx = reg; 95 if (force_user) { 96 regIdx = intRegInMode(MODE_USER, regIdx); 97 } 98 99 if (load) { 100 if (writeback && i == ones - 1) { 101 // If it's a writeback and this is the last register 102 // do the load into a temporary register which we'll move 103 // into the final one later 104 *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0, 105 up, addr); 106 } else { 107 // Otherwise just do it normally 108 if (reg == INTREG_PC && exception_ret) { 109 // This must be the exception return form of ldm. 110 *++uop = new MicroLdrRetUop(machInst, regIdx, 111 INTREG_UREG0, up, addr); 112 } else { 113 *++uop = new MicroLdrUop(machInst, regIdx, 114 INTREG_UREG0, up, addr); 115 } 116 } 117 } else { 118 *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr); 119 } 120 121 if (up) 122 addr += 4; 123 else 124 addr -= 4; 125 } 126 127 if (writeback && ones) { 128 // put the register update after we're done all loading 129 if (up) 130 *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4); 131 else 132 *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4); 133 134 // If this was a load move the last temporary value into place 135 // this way we can't take an exception after we update the base 136 // register. 137 if (load && reg == INTREG_PC && exception_ret) { 138 *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1); 139 } else if (load) { 140 *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1); 141 if (reg == INTREG_PC) { 142 (*uop)->setFlag(StaticInstBase::IsControl); 143 (*uop)->setFlag(StaticInstBase::IsCondControl); 144 (*uop)->setFlag(StaticInstBase::IsIndirectControl); 145 // This is created as a RAS POP 146 if (rn == INTREG_SP) 147 (*uop)->setFlag(StaticInstBase::IsReturn); 148 149 } 150 } 151 } 152 153 (*uop)->setLastMicroop(); 154 155 for (StaticInstPtr *curUop = microOps; 156 !(*curUop)->isLastMicroop(); curUop++) { 157 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get()); 158 assert(uopPtr); 159 uopPtr->setDelayedCommit(); 160 } 161} 162 163VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 164 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 165 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 166 PredMacroOp(mnem, machInst, __opClass) 167{ 168 assert(regs > 0 && regs <= 4); 169 assert(regs % elems == 0); 170 171 numMicroops = (regs > 2) ? 2 : 1; 172 bool wb = (rm != 15); 173 bool deinterleave = (elems > 1); 174 175 if (wb) numMicroops++; 176 if (deinterleave) numMicroops += (regs / elems); 177 microOps = new StaticInstPtr[numMicroops]; 178 179 RegIndex rMid = deinterleave ? NumFloatArchRegs : vd * 2; 180 181 uint32_t noAlign = TLB::MustBeOne; 182 183 unsigned uopIdx = 0; 184 switch (regs) { 185 case 4: 186 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 187 size, machInst, rMid, rn, 0, align); 188 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 189 size, machInst, rMid + 4, rn, 16, noAlign); 190 break; 191 case 3: 192 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 193 size, machInst, rMid, rn, 0, align); 194 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 195 size, machInst, rMid + 4, rn, 16, noAlign); 196 break; 197 case 2: 198 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 199 size, machInst, rMid, rn, 0, align); 200 break; 201 case 1: 202 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 203 size, machInst, rMid, rn, 0, align); 204 break; 205 default: 206 // Unknown number of registers 207 microOps[uopIdx++] = new Unknown(machInst); 208 } 209 if (wb) { 210 if (rm != 15 && rm != 13) { 211 microOps[uopIdx++] = 212 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 213 } else { 214 microOps[uopIdx++] = 215 new MicroAddiUop(machInst, rn, rn, regs * 8); 216 } 217 } 218 if (deinterleave) { 219 switch (elems) { 220 case 4: 221 assert(regs == 4); 222 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>( 223 size, machInst, vd * 2, rMid, inc * 2); 224 break; 225 case 3: 226 assert(regs == 3); 227 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>( 228 size, machInst, vd * 2, rMid, inc * 2); 229 break; 230 case 2: 231 assert(regs == 4 || regs == 2); 232 if (regs == 4) { 233 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 234 size, machInst, vd * 2, rMid, inc * 2); 235 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 236 size, machInst, vd * 2 + 2, rMid + 4, inc * 2); 237 } else { 238 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 239 size, machInst, vd * 2, rMid, inc * 2); 240 } 241 break; 242 default: 243 // Bad number of elements to deinterleave 244 microOps[uopIdx++] = new Unknown(machInst); 245 } 246 } 247 assert(uopIdx == numMicroops); 248 249 for (unsigned i = 0; i < numMicroops - 1; i++) { 250 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 251 assert(uopPtr); 252 uopPtr->setDelayedCommit(); 253 } 254 microOps[numMicroops - 1]->setLastMicroop(); 255} 256 257VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst, 258 OpClass __opClass, bool all, unsigned elems, 259 RegIndex rn, RegIndex vd, unsigned regs, 260 unsigned inc, uint32_t size, uint32_t align, 261 RegIndex rm, unsigned lane) : 262 PredMacroOp(mnem, machInst, __opClass) 263{ 264 assert(regs > 0 && regs <= 4); 265 assert(regs % elems == 0); 266 267 unsigned eBytes = (1 << size); 268 unsigned loadSize = eBytes * elems; 269 unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) / 270 sizeof(FloatRegBits); 271 272 assert(loadRegs > 0 && loadRegs <= 4); 273 274 numMicroops = 1; 275 bool wb = (rm != 15); 276 277 if (wb) numMicroops++; 278 numMicroops += (regs / elems); 279 microOps = new StaticInstPtr[numMicroops]; 280 281 RegIndex ufp0 = NumFloatArchRegs; 282 283 unsigned uopIdx = 0; 284 switch (loadSize) { 285 case 1: 286 microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>( 287 machInst, ufp0, rn, 0, align); 288 break; 289 case 2: 290 if (eBytes == 2) { 291 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>( 292 machInst, ufp0, rn, 0, align); 293 } else { 294 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>( 295 machInst, ufp0, rn, 0, align); 296 } 297 break; 298 case 3: 299 microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>( 300 machInst, ufp0, rn, 0, align); 301 break; 302 case 4: 303 switch (eBytes) { 304 case 1: 305 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>( 306 machInst, ufp0, rn, 0, align); 307 break; 308 case 2: 309 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>( 310 machInst, ufp0, rn, 0, align); 311 break; 312 case 4: 313 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>( 314 machInst, ufp0, rn, 0, align); 315 break; 316 } 317 break; 318 case 6: 319 microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>( 320 machInst, ufp0, rn, 0, align); 321 break; 322 case 8: 323 switch (eBytes) { 324 case 2: 325 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>( 326 machInst, ufp0, rn, 0, align); 327 break; 328 case 4: 329 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>( 330 machInst, ufp0, rn, 0, align); 331 break; 332 } 333 break; 334 case 12: 335 microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>( 336 machInst, ufp0, rn, 0, align); 337 break; 338 case 16: 339 microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>( 340 machInst, ufp0, rn, 0, align); 341 break; 342 default: 343 // Unrecognized load size 344 microOps[uopIdx++] = new Unknown(machInst); 345 } 346 if (wb) { 347 if (rm != 15 && rm != 13) { 348 microOps[uopIdx++] = 349 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 350 } else { 351 microOps[uopIdx++] = 352 new MicroAddiUop(machInst, rn, rn, loadSize); 353 } 354 } 355 switch (elems) { 356 case 4: 357 assert(regs == 4); 358 switch (size) { 359 case 0: 360 if (all) { 361 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>( 362 machInst, vd * 2, ufp0, inc * 2); 363 } else { 364 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>( 365 machInst, vd * 2, ufp0, inc * 2, lane); 366 } 367 break; 368 case 1: 369 if (all) { 370 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>( 371 machInst, vd * 2, ufp0, inc * 2); 372 } else { 373 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>( 374 machInst, vd * 2, ufp0, inc * 2, lane); 375 } 376 break; 377 case 2: 378 if (all) { 379 microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>( 380 machInst, vd * 2, ufp0, inc * 2); 381 } else { 382 microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>( 383 machInst, vd * 2, ufp0, inc * 2, lane); 384 } 385 break; 386 default: 387 // Bad size 388 microOps[uopIdx++] = new Unknown(machInst); 389 break; 390 } 391 break; 392 case 3: 393 assert(regs == 3); 394 switch (size) { 395 case 0: 396 if (all) { 397 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>( 398 machInst, vd * 2, ufp0, inc * 2); 399 } else { 400 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>( 401 machInst, vd * 2, ufp0, inc * 2, lane); 402 } 403 break; 404 case 1: 405 if (all) { 406 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>( 407 machInst, vd * 2, ufp0, inc * 2); 408 } else { 409 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>( 410 machInst, vd * 2, ufp0, inc * 2, lane); 411 } 412 break; 413 case 2: 414 if (all) { 415 microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>( 416 machInst, vd * 2, ufp0, inc * 2); 417 } else { 418 microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>( 419 machInst, vd * 2, ufp0, inc * 2, lane); 420 } 421 break; 422 default: 423 // Bad size 424 microOps[uopIdx++] = new Unknown(machInst); 425 break; 426 } 427 break; 428 case 2: 429 assert(regs == 2); 430 assert(loadRegs <= 2); 431 switch (size) { 432 case 0: 433 if (all) { 434 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>( 435 machInst, vd * 2, ufp0, inc * 2); 436 } else { 437 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>( 438 machInst, vd * 2, ufp0, inc * 2, lane); 439 } 440 break; 441 case 1: 442 if (all) { 443 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>( 444 machInst, vd * 2, ufp0, inc * 2); 445 } else { 446 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>( 447 machInst, vd * 2, ufp0, inc * 2, lane); 448 } 449 break; 450 case 2: 451 if (all) { 452 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>( 453 machInst, vd * 2, ufp0, inc * 2); 454 } else { 455 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>( 456 machInst, vd * 2, ufp0, inc * 2, lane); 457 } 458 break; 459 default: 460 // Bad size 461 microOps[uopIdx++] = new Unknown(machInst); 462 break; 463 } 464 break; 465 case 1: 466 assert(regs == 1 || (all && regs == 2)); 467 assert(loadRegs <= 2); 468 for (unsigned offset = 0; offset < regs; offset++) { 469 switch (size) { 470 case 0: 471 if (all) { 472 microOps[uopIdx++] = 473 new MicroUnpackAllNeon2to2Uop<uint8_t>( 474 machInst, (vd + offset) * 2, ufp0, inc * 2); 475 } else { 476 microOps[uopIdx++] = 477 new MicroUnpackNeon2to2Uop<uint8_t>( 478 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 479 } 480 break; 481 case 1: 482 if (all) { 483 microOps[uopIdx++] = 484 new MicroUnpackAllNeon2to2Uop<uint16_t>( 485 machInst, (vd + offset) * 2, ufp0, inc * 2); 486 } else { 487 microOps[uopIdx++] = 488 new MicroUnpackNeon2to2Uop<uint16_t>( 489 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 490 } 491 break; 492 case 2: 493 if (all) { 494 microOps[uopIdx++] = 495 new MicroUnpackAllNeon2to2Uop<uint32_t>( 496 machInst, (vd + offset) * 2, ufp0, inc * 2); 497 } else { 498 microOps[uopIdx++] = 499 new MicroUnpackNeon2to2Uop<uint32_t>( 500 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 501 } 502 break; 503 default: 504 // Bad size 505 microOps[uopIdx++] = new Unknown(machInst); 506 break; 507 } 508 } 509 break; 510 default: 511 // Bad number of elements to unpack 512 microOps[uopIdx++] = new Unknown(machInst); 513 } 514 assert(uopIdx == numMicroops); 515 516 for (unsigned i = 0; i < numMicroops - 1; i++) { 517 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 518 assert(uopPtr); 519 uopPtr->setDelayedCommit(); 520 } 521 microOps[numMicroops - 1]->setLastMicroop(); 522} 523 524VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 525 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 526 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 527 PredMacroOp(mnem, machInst, __opClass) 528{ 529 assert(regs > 0 && regs <= 4); 530 assert(regs % elems == 0); 531 532 numMicroops = (regs > 2) ? 2 : 1; 533 bool wb = (rm != 15); 534 bool interleave = (elems > 1); 535 536 if (wb) numMicroops++; 537 if (interleave) numMicroops += (regs / elems); 538 microOps = new StaticInstPtr[numMicroops]; 539 540 uint32_t noAlign = TLB::MustBeOne; 541 542 RegIndex rMid = interleave ? NumFloatArchRegs : vd * 2; 543 544 unsigned uopIdx = 0; 545 if (interleave) { 546 switch (elems) { 547 case 4: 548 assert(regs == 4); 549 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>( 550 size, machInst, rMid, vd * 2, inc * 2); 551 break; 552 case 3: 553 assert(regs == 3); 554 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>( 555 size, machInst, rMid, vd * 2, inc * 2); 556 break; 557 case 2: 558 assert(regs == 4 || regs == 2); 559 if (regs == 4) { 560 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 561 size, machInst, rMid, vd * 2, inc * 2); 562 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 563 size, machInst, rMid + 4, vd * 2 + 2, inc * 2); 564 } else { 565 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 566 size, machInst, rMid, vd * 2, inc * 2); 567 } 568 break; 569 default: 570 // Bad number of elements to interleave 571 microOps[uopIdx++] = new Unknown(machInst); 572 } 573 } 574 switch (regs) { 575 case 4: 576 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 577 size, machInst, rMid, rn, 0, align); 578 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 579 size, machInst, rMid + 4, rn, 16, noAlign); 580 break; 581 case 3: 582 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 583 size, machInst, rMid, rn, 0, align); 584 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 585 size, machInst, rMid + 4, rn, 16, noAlign); 586 break; 587 case 2: 588 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 589 size, machInst, rMid, rn, 0, align); 590 break; 591 case 1: 592 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 593 size, machInst, rMid, rn, 0, align); 594 break; 595 default: 596 // Unknown number of registers 597 microOps[uopIdx++] = new Unknown(machInst); 598 } 599 if (wb) { 600 if (rm != 15 && rm != 13) { 601 microOps[uopIdx++] = 602 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 603 } else { 604 microOps[uopIdx++] = 605 new MicroAddiUop(machInst, rn, rn, regs * 8); 606 } 607 } 608 assert(uopIdx == numMicroops); 609 610 for (unsigned i = 0; i < numMicroops - 1; i++) { 611 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 612 assert(uopPtr); 613 uopPtr->setDelayedCommit(); 614 } 615 microOps[numMicroops - 1]->setLastMicroop(); 616} 617 618VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst, 619 OpClass __opClass, bool all, unsigned elems, 620 RegIndex rn, RegIndex vd, unsigned regs, 621 unsigned inc, uint32_t size, uint32_t align, 622 RegIndex rm, unsigned lane) : 623 PredMacroOp(mnem, machInst, __opClass) 624{ 625 assert(!all); 626 assert(regs > 0 && regs <= 4); 627 assert(regs % elems == 0); 628 629 unsigned eBytes = (1 << size); 630 unsigned storeSize = eBytes * elems; 631 unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) / 632 sizeof(FloatRegBits); 633 634 assert(storeRegs > 0 && storeRegs <= 4); 635 636 numMicroops = 1; 637 bool wb = (rm != 15); 638 639 if (wb) numMicroops++; 640 numMicroops += (regs / elems); 641 microOps = new StaticInstPtr[numMicroops]; 642 643 RegIndex ufp0 = NumFloatArchRegs; 644 645 unsigned uopIdx = 0; 646 switch (elems) { 647 case 4: 648 assert(regs == 4); 649 switch (size) { 650 case 0: 651 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>( 652 machInst, ufp0, vd * 2, inc * 2, lane); 653 break; 654 case 1: 655 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>( 656 machInst, ufp0, vd * 2, inc * 2, lane); 657 break; 658 case 2: 659 microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>( 660 machInst, ufp0, vd * 2, inc * 2, lane); 661 break; 662 default: 663 // Bad size 664 microOps[uopIdx++] = new Unknown(machInst); 665 break; 666 } 667 break; 668 case 3: 669 assert(regs == 3); 670 switch (size) { 671 case 0: 672 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>( 673 machInst, ufp0, vd * 2, inc * 2, lane); 674 break; 675 case 1: 676 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>( 677 machInst, ufp0, vd * 2, inc * 2, lane); 678 break; 679 case 2: 680 microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>( 681 machInst, ufp0, vd * 2, inc * 2, lane); 682 break; 683 default: 684 // Bad size 685 microOps[uopIdx++] = new Unknown(machInst); 686 break; 687 } 688 break; 689 case 2: 690 assert(regs == 2); 691 assert(storeRegs <= 2); 692 switch (size) { 693 case 0: 694 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>( 695 machInst, ufp0, vd * 2, inc * 2, lane); 696 break; 697 case 1: 698 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>( 699 machInst, ufp0, vd * 2, inc * 2, lane); 700 break; 701 case 2: 702 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>( 703 machInst, ufp0, vd * 2, inc * 2, lane); 704 break; 705 default: 706 // Bad size 707 microOps[uopIdx++] = new Unknown(machInst); 708 break; 709 } 710 break; 711 case 1: 712 assert(regs == 1 || (all && regs == 2)); 713 assert(storeRegs <= 2); 714 for (unsigned offset = 0; offset < regs; offset++) { 715 switch (size) { 716 case 0: 717 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>( 718 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 719 break; 720 case 1: 721 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>( 722 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 723 break; 724 case 2: 725 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>( 726 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 727 break; 728 default: 729 // Bad size 730 microOps[uopIdx++] = new Unknown(machInst); 731 break; 732 } 733 } 734 break; 735 default: 736 // Bad number of elements to unpack 737 microOps[uopIdx++] = new Unknown(machInst); 738 } 739 switch (storeSize) { 740 case 1: 741 microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>( 742 machInst, ufp0, rn, 0, align); 743 break; 744 case 2: 745 if (eBytes == 2) { 746 microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>( 747 machInst, ufp0, rn, 0, align); 748 } else { 749 microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>( 750 machInst, ufp0, rn, 0, align); 751 } 752 break; 753 case 3: 754 microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>( 755 machInst, ufp0, rn, 0, align); 756 break; 757 case 4: 758 switch (eBytes) { 759 case 1: 760 microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>( 761 machInst, ufp0, rn, 0, align); 762 break; 763 case 2: 764 microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>( 765 machInst, ufp0, rn, 0, align); 766 break; 767 case 4: 768 microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>( 769 machInst, ufp0, rn, 0, align); 770 break; 771 } 772 break; 773 case 6: 774 microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>( 775 machInst, ufp0, rn, 0, align); 776 break; 777 case 8: 778 switch (eBytes) { 779 case 2: 780 microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>( 781 machInst, ufp0, rn, 0, align); 782 break; 783 case 4: 784 microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>( 785 machInst, ufp0, rn, 0, align); 786 break; 787 } 788 break; 789 case 12: 790 microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>( 791 machInst, ufp0, rn, 0, align); 792 break; 793 case 16: 794 microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>( 795 machInst, ufp0, rn, 0, align); 796 break; 797 default: 798 // Bad store size 799 microOps[uopIdx++] = new Unknown(machInst); 800 } 801 if (wb) { 802 if (rm != 15 && rm != 13) { 803 microOps[uopIdx++] = 804 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL); 805 } else { 806 microOps[uopIdx++] = 807 new MicroAddiUop(machInst, rn, rn, storeSize); 808 } 809 } 810 assert(uopIdx == numMicroops); 811 812 for (unsigned i = 0; i < numMicroops - 1; i++) { 813 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 814 assert(uopPtr); 815 uopPtr->setDelayedCommit(); 816 } 817 microOps[numMicroops - 1]->setLastMicroop(); 818} 819 820MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst, 821 OpClass __opClass, IntRegIndex rn, 822 RegIndex vd, bool single, bool up, 823 bool writeback, bool load, uint32_t offset) : 824 PredMacroOp(mnem, machInst, __opClass) 825{ 826 int i = 0; 827 828 // The lowest order bit selects fldmx (set) or fldmd (clear). These seem 829 // to be functionally identical except that fldmx is deprecated. For now 830 // we'll assume they're otherwise interchangable. 831 int count = (single ? offset : (offset / 2)); 832 if (count == 0 || count > NumFloatArchRegs) 833 warn_once("Bad offset field for VFP load/store multiple.\n"); 834 if (count == 0) { 835 // Force there to be at least one microop so the macroop makes sense. 836 writeback = true; 837 } 838 if (count > NumFloatArchRegs) 839 count = NumFloatArchRegs; 840 841 numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0); 842 microOps = new StaticInstPtr[numMicroops]; 843 844 int64_t addr = 0; 845 846 if (!up) 847 addr = 4 * offset; 848 849 bool tempUp = up; 850 for (int j = 0; j < count; j++) { 851 if (load) { 852 if (single) { 853 microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, 854 tempUp, addr); 855 } else { 856 microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn, 857 tempUp, addr); 858 microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp, 859 addr + (up ? 4 : -4)); 860 } 861 } else { 862 if (single) { 863 microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, 864 tempUp, addr); 865 } else { 866 microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn, 867 tempUp, addr); 868 microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp, 869 addr + (up ? 4 : -4)); 870 } 871 } 872 if (!tempUp) { 873 addr -= (single ? 4 : 8); 874 // The microops don't handle negative displacement, so turn if we 875 // hit zero, flip polarity and start adding. 876 if (addr <= 0) { 877 tempUp = true; 878 addr = -addr; 879 } 880 } else { 881 addr += (single ? 4 : 8); 882 } 883 } 884 885 if (writeback) { 886 if (up) { 887 microOps[i++] = 888 new MicroAddiUop(machInst, rn, rn, 4 * offset); 889 } else { 890 microOps[i++] = 891 new MicroSubiUop(machInst, rn, rn, 4 * offset); 892 } 893 } 894 895 assert(numMicroops == i); 896 microOps[numMicroops - 1]->setLastMicroop(); 897 898 for (StaticInstPtr *curUop = microOps; 899 !(*curUop)->isLastMicroop(); curUop++) { 900 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get()); 901 assert(uopPtr); 902 uopPtr->setDelayedCommit(); 903 } 904} 905 906std::string 907MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 908{ 909 std::stringstream ss; 910 printMnemonic(ss); 911 printReg(ss, ura); 912 ss << ", "; 913 printReg(ss, urb); 914 ss << ", "; 915 ccprintf(ss, "#%d", imm); 916 return ss.str(); 917} 918 919std::string 920MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const 921{ 922 std::stringstream ss; 923 printMnemonic(ss); 924 ss << "[PC,CPSR]"; 925 return ss.str(); 926} 927 928std::string 929MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const 930{ 931 std::stringstream ss; 932 printMnemonic(ss); 933 printReg(ss, ura); 934 ss << ", "; 935 printReg(ss, urb); 936 return ss.str(); 937} 938 939std::string 940MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 941{ 942 std::stringstream ss; 943 printMnemonic(ss); 944 printReg(ss, ura); 945 ss << ", "; 946 printReg(ss, urb); 947 ss << ", "; 948 printReg(ss, urc); 949 return ss.str(); 950} 951 952std::string 953MicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 954{ 955 std::stringstream ss; 956 printMnemonic(ss); 957 printReg(ss, ura); 958 ss << ", ["; 959 printReg(ss, urb); 960 ss << ", "; 961 ccprintf(ss, "#%d", imm); 962 ss << "]"; 963 return ss.str(); 964} 965 966} 967