macromem.cc revision 7639:8c09b7ff5b57
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 46using namespace ArmISAInst; 47 48namespace ArmISA 49{ 50 51MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst, 52 OpClass __opClass, IntRegIndex rn, 53 bool index, bool up, bool user, bool writeback, 54 bool load, uint32_t reglist) : 55 PredMacroOp(mnem, machInst, __opClass) 56{ 57 uint32_t regs = reglist; 58 uint32_t ones = number_of_ones(reglist); 59 // Remember that writeback adds a uop 60 numMicroops = ones + (writeback ? 1 : 0) + 1; 61 microOps = new StaticInstPtr[numMicroops]; 62 uint32_t addr = 0; 63 64 if (!up) 65 addr = (ones << 2) - 4; 66 67 if (!index) 68 addr += 4; 69 70 StaticInstPtr *uop = microOps; 71 StaticInstPtr wbUop; 72 if (writeback) { 73 if (up) { 74 wbUop = new MicroAddiUop(machInst, rn, rn, ones * 4); 75 } else { 76 wbUop = new MicroSubiUop(machInst, rn, rn, ones * 4); 77 } 78 } 79 80 // Add 0 to Rn and stick it in ureg0. 81 // This is equivalent to a move. 82 *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0); 83 84 // Write back at the start for loads. This covers the ldm exception return 85 // case where the base needs to be written in the old mode. Stores may need 86 // the original value of the base, but they don't change mode and can 87 // write back at the end like before. 88 if (load && writeback) { 89 *++uop = wbUop; 90 } 91 92 unsigned reg = 0; 93 bool force_user = user & !bits(reglist, 15); 94 bool exception_ret = user & bits(reglist, 15); 95 96 for (int i = 0; i < ones; i++) { 97 // Find the next register. 98 while (!bits(regs, reg)) 99 reg++; 100 replaceBits(regs, reg, 0); 101 102 unsigned regIdx = reg; 103 if (force_user) { 104 regIdx = intRegInMode(MODE_USER, regIdx); 105 } 106 107 if (load) { 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 } else { 117 *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr); 118 } 119 120 if (up) 121 addr += 4; 122 else 123 addr -= 4; 124 } 125 126 if (!load && writeback) { 127 *++uop = wbUop; 128 } 129 130 (*uop)->setLastMicroop(); 131 132 for (StaticInstPtr *curUop = microOps; 133 !(*curUop)->isLastMicroop(); curUop++) { 134 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get()); 135 assert(uopPtr); 136 uopPtr->setDelayedCommit(); 137 } 138} 139 140VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 141 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 142 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 143 PredMacroOp(mnem, machInst, __opClass) 144{ 145 assert(regs > 0 && regs <= 4); 146 assert(regs % elems == 0); 147 148 numMicroops = (regs > 2) ? 2 : 1; 149 bool wb = (rm != 15); 150 bool deinterleave = (elems > 1); 151 152 if (wb) numMicroops++; 153 if (deinterleave) numMicroops += (regs / elems); 154 microOps = new StaticInstPtr[numMicroops]; 155 156 RegIndex rMid = deinterleave ? NumFloatArchRegs : vd * 2; 157 158 uint32_t noAlign = TLB::MustBeOne; 159 160 unsigned uopIdx = 0; 161 switch (regs) { 162 case 4: 163 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 164 size, machInst, rMid, rn, 0, align); 165 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 166 size, machInst, rMid + 4, rn, 16, noAlign); 167 break; 168 case 3: 169 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 170 size, machInst, rMid, rn, 0, align); 171 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 172 size, machInst, rMid + 4, rn, 16, noAlign); 173 break; 174 case 2: 175 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>( 176 size, machInst, rMid, rn, 0, align); 177 break; 178 case 1: 179 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>( 180 size, machInst, rMid, rn, 0, align); 181 break; 182 default: 183 panic("Unrecognized number of registers %d.\n", regs); 184 } 185 if (wb) { 186 if (rm != 15 && rm != 13) { 187 microOps[uopIdx++] = 188 new MicroAddUop(machInst, rn, rn, rm); 189 } else { 190 microOps[uopIdx++] = 191 new MicroAddiUop(machInst, rn, rn, regs * 8); 192 } 193 } 194 if (deinterleave) { 195 switch (elems) { 196 case 4: 197 assert(regs == 4); 198 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>( 199 size, machInst, vd * 2, rMid, inc * 2); 200 break; 201 case 3: 202 assert(regs == 3); 203 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>( 204 size, machInst, vd * 2, rMid, inc * 2); 205 break; 206 case 2: 207 assert(regs == 4 || regs == 2); 208 if (regs == 4) { 209 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 210 size, machInst, vd * 2, rMid, inc * 2); 211 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 212 size, machInst, vd * 2 + 2, rMid + 4, inc * 2); 213 } else { 214 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>( 215 size, machInst, vd * 2, rMid, inc * 2); 216 } 217 break; 218 default: 219 panic("Bad number of elements to deinterleave %d.\n", elems); 220 } 221 } 222 assert(uopIdx == numMicroops); 223 224 for (unsigned i = 0; i < numMicroops - 1; i++) { 225 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 226 assert(uopPtr); 227 uopPtr->setDelayedCommit(); 228 } 229 microOps[numMicroops - 1]->setLastMicroop(); 230} 231 232VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst, 233 OpClass __opClass, bool all, unsigned elems, 234 RegIndex rn, RegIndex vd, unsigned regs, 235 unsigned inc, uint32_t size, uint32_t align, 236 RegIndex rm, unsigned lane) : 237 PredMacroOp(mnem, machInst, __opClass) 238{ 239 assert(regs > 0 && regs <= 4); 240 assert(regs % elems == 0); 241 242 unsigned eBytes = (1 << size); 243 unsigned loadSize = eBytes * elems; 244 unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) / 245 sizeof(FloatRegBits); 246 247 assert(loadRegs > 0 && loadRegs <= 4); 248 249 numMicroops = 1; 250 bool wb = (rm != 15); 251 252 if (wb) numMicroops++; 253 numMicroops += (regs / elems); 254 microOps = new StaticInstPtr[numMicroops]; 255 256 RegIndex ufp0 = NumFloatArchRegs; 257 258 unsigned uopIdx = 0; 259 switch (loadSize) { 260 case 1: 261 microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>( 262 machInst, ufp0, rn, 0, align); 263 break; 264 case 2: 265 if (eBytes == 2) { 266 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>( 267 machInst, ufp0, rn, 0, align); 268 } else { 269 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>( 270 machInst, ufp0, rn, 0, align); 271 } 272 break; 273 case 3: 274 microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>( 275 machInst, ufp0, rn, 0, align); 276 break; 277 case 4: 278 switch (eBytes) { 279 case 1: 280 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>( 281 machInst, ufp0, rn, 0, align); 282 break; 283 case 2: 284 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>( 285 machInst, ufp0, rn, 0, align); 286 break; 287 case 4: 288 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>( 289 machInst, ufp0, rn, 0, align); 290 break; 291 } 292 break; 293 case 6: 294 microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>( 295 machInst, ufp0, rn, 0, align); 296 break; 297 case 8: 298 switch (eBytes) { 299 case 2: 300 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>( 301 machInst, ufp0, rn, 0, align); 302 break; 303 case 4: 304 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>( 305 machInst, ufp0, rn, 0, align); 306 break; 307 } 308 break; 309 case 12: 310 microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>( 311 machInst, ufp0, rn, 0, align); 312 break; 313 case 16: 314 microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>( 315 machInst, ufp0, rn, 0, align); 316 break; 317 default: 318 panic("Unrecognized load size %d.\n", regs); 319 } 320 if (wb) { 321 if (rm != 15 && rm != 13) { 322 microOps[uopIdx++] = 323 new MicroAddUop(machInst, rn, rn, rm); 324 } else { 325 microOps[uopIdx++] = 326 new MicroAddiUop(machInst, rn, rn, loadSize); 327 } 328 } 329 switch (elems) { 330 case 4: 331 assert(regs == 4); 332 switch (size) { 333 case 0: 334 if (all) { 335 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>( 336 machInst, vd * 2, ufp0, inc * 2); 337 } else { 338 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>( 339 machInst, vd * 2, ufp0, inc * 2, lane); 340 } 341 break; 342 case 1: 343 if (all) { 344 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>( 345 machInst, vd * 2, ufp0, inc * 2); 346 } else { 347 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>( 348 machInst, vd * 2, ufp0, inc * 2, lane); 349 } 350 break; 351 case 2: 352 if (all) { 353 microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>( 354 machInst, vd * 2, ufp0, inc * 2); 355 } else { 356 microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>( 357 machInst, vd * 2, ufp0, inc * 2, lane); 358 } 359 break; 360 default: 361 panic("Bad size %d.\n", size); 362 break; 363 } 364 break; 365 case 3: 366 assert(regs == 3); 367 switch (size) { 368 case 0: 369 if (all) { 370 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>( 371 machInst, vd * 2, ufp0, inc * 2); 372 } else { 373 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>( 374 machInst, vd * 2, ufp0, inc * 2, lane); 375 } 376 break; 377 case 1: 378 if (all) { 379 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>( 380 machInst, vd * 2, ufp0, inc * 2); 381 } else { 382 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>( 383 machInst, vd * 2, ufp0, inc * 2, lane); 384 } 385 break; 386 case 2: 387 if (all) { 388 microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>( 389 machInst, vd * 2, ufp0, inc * 2); 390 } else { 391 microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>( 392 machInst, vd * 2, ufp0, inc * 2, lane); 393 } 394 break; 395 default: 396 panic("Bad size %d.\n", size); 397 break; 398 } 399 break; 400 case 2: 401 assert(regs == 2); 402 assert(loadRegs <= 2); 403 switch (size) { 404 case 0: 405 if (all) { 406 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>( 407 machInst, vd * 2, ufp0, inc * 2); 408 } else { 409 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>( 410 machInst, vd * 2, ufp0, inc * 2, lane); 411 } 412 break; 413 case 1: 414 if (all) { 415 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>( 416 machInst, vd * 2, ufp0, inc * 2); 417 } else { 418 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>( 419 machInst, vd * 2, ufp0, inc * 2, lane); 420 } 421 break; 422 case 2: 423 if (all) { 424 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>( 425 machInst, vd * 2, ufp0, inc * 2); 426 } else { 427 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>( 428 machInst, vd * 2, ufp0, inc * 2, lane); 429 } 430 break; 431 default: 432 panic("Bad size %d.\n", size); 433 break; 434 } 435 break; 436 case 1: 437 assert(regs == 1 || (all && regs == 2)); 438 assert(loadRegs <= 2); 439 for (unsigned offset = 0; offset < regs; offset++) { 440 switch (size) { 441 case 0: 442 if (all) { 443 microOps[uopIdx++] = 444 new MicroUnpackAllNeon2to2Uop<uint8_t>( 445 machInst, (vd + offset) * 2, ufp0, inc * 2); 446 } else { 447 microOps[uopIdx++] = 448 new MicroUnpackNeon2to2Uop<uint8_t>( 449 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 450 } 451 break; 452 case 1: 453 if (all) { 454 microOps[uopIdx++] = 455 new MicroUnpackAllNeon2to2Uop<uint16_t>( 456 machInst, (vd + offset) * 2, ufp0, inc * 2); 457 } else { 458 microOps[uopIdx++] = 459 new MicroUnpackNeon2to2Uop<uint16_t>( 460 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 461 } 462 break; 463 case 2: 464 if (all) { 465 microOps[uopIdx++] = 466 new MicroUnpackAllNeon2to2Uop<uint32_t>( 467 machInst, (vd + offset) * 2, ufp0, inc * 2); 468 } else { 469 microOps[uopIdx++] = 470 new MicroUnpackNeon2to2Uop<uint32_t>( 471 machInst, (vd + offset) * 2, ufp0, inc * 2, lane); 472 } 473 break; 474 default: 475 panic("Bad size %d.\n", size); 476 break; 477 } 478 } 479 break; 480 default: 481 panic("Bad number of elements to unpack %d.\n", elems); 482 } 483 assert(uopIdx == numMicroops); 484 485 for (unsigned i = 0; i < numMicroops - 1; i++) { 486 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 487 assert(uopPtr); 488 uopPtr->setDelayedCommit(); 489 } 490 microOps[numMicroops - 1]->setLastMicroop(); 491} 492 493VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 494 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 495 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 496 PredMacroOp(mnem, machInst, __opClass) 497{ 498 assert(regs > 0 && regs <= 4); 499 assert(regs % elems == 0); 500 501 numMicroops = (regs > 2) ? 2 : 1; 502 bool wb = (rm != 15); 503 bool interleave = (elems > 1); 504 505 if (wb) numMicroops++; 506 if (interleave) numMicroops += (regs / elems); 507 microOps = new StaticInstPtr[numMicroops]; 508 509 uint32_t noAlign = TLB::MustBeOne; 510 511 RegIndex rMid = interleave ? NumFloatArchRegs : vd * 2; 512 513 unsigned uopIdx = 0; 514 if (interleave) { 515 switch (elems) { 516 case 4: 517 assert(regs == 4); 518 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>( 519 size, machInst, rMid, vd * 2, inc * 2); 520 break; 521 case 3: 522 assert(regs == 3); 523 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>( 524 size, machInst, rMid, vd * 2, inc * 2); 525 break; 526 case 2: 527 assert(regs == 4 || regs == 2); 528 if (regs == 4) { 529 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 530 size, machInst, rMid, vd * 2, inc * 2); 531 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 532 size, machInst, rMid + 4, vd * 2 + 2, inc * 2); 533 } else { 534 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>( 535 size, machInst, rMid, vd * 2, inc * 2); 536 } 537 break; 538 default: 539 panic("Bad number of elements to interleave %d.\n", elems); 540 } 541 } 542 switch (regs) { 543 case 4: 544 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 545 size, machInst, rMid, rn, 0, align); 546 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 547 size, machInst, rMid + 4, rn, 16, noAlign); 548 break; 549 case 3: 550 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 551 size, machInst, rMid, rn, 0, align); 552 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 553 size, machInst, rMid + 4, rn, 16, noAlign); 554 break; 555 case 2: 556 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>( 557 size, machInst, rMid, rn, 0, align); 558 break; 559 case 1: 560 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>( 561 size, machInst, rMid, rn, 0, align); 562 break; 563 default: 564 panic("Unrecognized number of registers %d.\n", regs); 565 } 566 if (wb) { 567 if (rm != 15 && rm != 13) { 568 microOps[uopIdx++] = 569 new MicroAddUop(machInst, rn, rn, rm); 570 } else { 571 microOps[uopIdx++] = 572 new MicroAddiUop(machInst, rn, rn, regs * 8); 573 } 574 } 575 assert(uopIdx == numMicroops); 576 577 for (unsigned i = 0; i < numMicroops - 1; i++) { 578 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 579 assert(uopPtr); 580 uopPtr->setDelayedCommit(); 581 } 582 microOps[numMicroops - 1]->setLastMicroop(); 583} 584 585VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst, 586 OpClass __opClass, bool all, unsigned elems, 587 RegIndex rn, RegIndex vd, unsigned regs, 588 unsigned inc, uint32_t size, uint32_t align, 589 RegIndex rm, unsigned lane) : 590 PredMacroOp(mnem, machInst, __opClass) 591{ 592 assert(!all); 593 assert(regs > 0 && regs <= 4); 594 assert(regs % elems == 0); 595 596 unsigned eBytes = (1 << size); 597 unsigned storeSize = eBytes * elems; 598 unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) / 599 sizeof(FloatRegBits); 600 601 assert(storeRegs > 0 && storeRegs <= 4); 602 603 numMicroops = 1; 604 bool wb = (rm != 15); 605 606 if (wb) numMicroops++; 607 numMicroops += (regs / elems); 608 microOps = new StaticInstPtr[numMicroops]; 609 610 RegIndex ufp0 = NumFloatArchRegs; 611 612 unsigned uopIdx = 0; 613 switch (elems) { 614 case 4: 615 assert(regs == 4); 616 switch (size) { 617 case 0: 618 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>( 619 machInst, ufp0, vd * 2, inc * 2, lane); 620 break; 621 case 1: 622 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>( 623 machInst, ufp0, vd * 2, inc * 2, lane); 624 break; 625 case 2: 626 microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>( 627 machInst, ufp0, vd * 2, inc * 2, lane); 628 break; 629 default: 630 panic("Bad size %d.\n", size); 631 break; 632 } 633 break; 634 case 3: 635 assert(regs == 3); 636 switch (size) { 637 case 0: 638 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>( 639 machInst, ufp0, vd * 2, inc * 2, lane); 640 break; 641 case 1: 642 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>( 643 machInst, ufp0, vd * 2, inc * 2, lane); 644 break; 645 case 2: 646 microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>( 647 machInst, ufp0, vd * 2, inc * 2, lane); 648 break; 649 default: 650 panic("Bad size %d.\n", size); 651 break; 652 } 653 break; 654 case 2: 655 assert(regs == 2); 656 assert(storeRegs <= 2); 657 switch (size) { 658 case 0: 659 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>( 660 machInst, ufp0, vd * 2, inc * 2, lane); 661 break; 662 case 1: 663 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>( 664 machInst, ufp0, vd * 2, inc * 2, lane); 665 break; 666 case 2: 667 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>( 668 machInst, ufp0, vd * 2, inc * 2, lane); 669 break; 670 default: 671 panic("Bad size %d.\n", size); 672 break; 673 } 674 break; 675 case 1: 676 assert(regs == 1 || (all && regs == 2)); 677 assert(storeRegs <= 2); 678 for (unsigned offset = 0; offset < regs; offset++) { 679 switch (size) { 680 case 0: 681 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>( 682 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 683 break; 684 case 1: 685 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>( 686 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 687 break; 688 case 2: 689 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>( 690 machInst, ufp0, (vd + offset) * 2, inc * 2, lane); 691 break; 692 default: 693 panic("Bad size %d.\n", size); 694 break; 695 } 696 } 697 break; 698 default: 699 panic("Bad number of elements to pack %d.\n", elems); 700 } 701 switch (storeSize) { 702 case 1: 703 microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>( 704 machInst, ufp0, rn, 0, align); 705 break; 706 case 2: 707 if (eBytes == 2) { 708 microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>( 709 machInst, ufp0, rn, 0, align); 710 } else { 711 microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>( 712 machInst, ufp0, rn, 0, align); 713 } 714 break; 715 case 3: 716 microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>( 717 machInst, ufp0, rn, 0, align); 718 break; 719 case 4: 720 switch (eBytes) { 721 case 1: 722 microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>( 723 machInst, ufp0, rn, 0, align); 724 break; 725 case 2: 726 microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>( 727 machInst, ufp0, rn, 0, align); 728 break; 729 case 4: 730 microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>( 731 machInst, ufp0, rn, 0, align); 732 break; 733 } 734 break; 735 case 6: 736 microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>( 737 machInst, ufp0, rn, 0, align); 738 break; 739 case 8: 740 switch (eBytes) { 741 case 2: 742 microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>( 743 machInst, ufp0, rn, 0, align); 744 break; 745 case 4: 746 microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>( 747 machInst, ufp0, rn, 0, align); 748 break; 749 } 750 break; 751 case 12: 752 microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>( 753 machInst, ufp0, rn, 0, align); 754 break; 755 case 16: 756 microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>( 757 machInst, ufp0, rn, 0, align); 758 break; 759 default: 760 panic("Unrecognized store size %d.\n", regs); 761 } 762 if (wb) { 763 if (rm != 15 && rm != 13) { 764 microOps[uopIdx++] = 765 new MicroAddUop(machInst, rn, rn, rm); 766 } else { 767 microOps[uopIdx++] = 768 new MicroAddiUop(machInst, rn, rn, storeSize); 769 } 770 } 771 assert(uopIdx == numMicroops); 772 773 for (unsigned i = 0; i < numMicroops - 1; i++) { 774 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get()); 775 assert(uopPtr); 776 uopPtr->setDelayedCommit(); 777 } 778 microOps[numMicroops - 1]->setLastMicroop(); 779} 780 781MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst, 782 OpClass __opClass, IntRegIndex rn, 783 RegIndex vd, bool single, bool up, 784 bool writeback, bool load, uint32_t offset) : 785 PredMacroOp(mnem, machInst, __opClass) 786{ 787 int i = 0; 788 789 // The lowest order bit selects fldmx (set) or fldmd (clear). These seem 790 // to be functionally identical except that fldmx is deprecated. For now 791 // we'll assume they're otherwise interchangable. 792 int count = (single ? offset : (offset / 2)); 793 if (count == 0 || count > NumFloatArchRegs) 794 warn_once("Bad offset field for VFP load/store multiple.\n"); 795 if (count == 0) { 796 // Force there to be at least one microop so the macroop makes sense. 797 writeback = true; 798 } 799 if (count > NumFloatArchRegs) 800 count = NumFloatArchRegs; 801 802 numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0); 803 microOps = new StaticInstPtr[numMicroops]; 804 805 int64_t addr = 0; 806 807 if (!up) 808 addr = 4 * offset; 809 810 bool tempUp = up; 811 for (int j = 0; j < count; j++) { 812 if (load) { 813 if (single) { 814 microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn, 815 tempUp, addr); 816 } else { 817 microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn, 818 tempUp, addr); 819 microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp, 820 addr + (up ? 4 : -4)); 821 } 822 } else { 823 if (single) { 824 microOps[i++] = new MicroStrFpUop(machInst, vd++, rn, 825 tempUp, addr); 826 } else { 827 microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn, 828 tempUp, addr); 829 microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp, 830 addr + (up ? 4 : -4)); 831 } 832 } 833 if (!tempUp) { 834 addr -= (single ? 4 : 8); 835 // The microops don't handle negative displacement, so turn if we 836 // hit zero, flip polarity and start adding. 837 if (addr <= 0) { 838 tempUp = true; 839 addr = -addr; 840 } 841 } else { 842 addr += (single ? 4 : 8); 843 } 844 } 845 846 if (writeback) { 847 if (up) { 848 microOps[i++] = 849 new MicroAddiUop(machInst, rn, rn, 4 * offset); 850 } else { 851 microOps[i++] = 852 new MicroSubiUop(machInst, rn, rn, 4 * offset); 853 } 854 } 855 856 assert(numMicroops == i); 857 microOps[numMicroops - 1]->setLastMicroop(); 858 859 for (StaticInstPtr *curUop = microOps; 860 !(*curUop)->isLastMicroop(); curUop++) { 861 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get()); 862 assert(uopPtr); 863 uopPtr->setDelayedCommit(); 864 } 865} 866 867std::string 868MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 869{ 870 std::stringstream ss; 871 printMnemonic(ss); 872 printReg(ss, ura); 873 ss << ", "; 874 printReg(ss, urb); 875 ss << ", "; 876 ccprintf(ss, "#%d", imm); 877 return ss.str(); 878} 879 880std::string 881MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 882{ 883 std::stringstream ss; 884 printMnemonic(ss); 885 printReg(ss, ura); 886 ss << ", "; 887 printReg(ss, urb); 888 ss << ", "; 889 printReg(ss, urc); 890 return ss.str(); 891} 892 893std::string 894MicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 895{ 896 std::stringstream ss; 897 printMnemonic(ss); 898 printReg(ss, ura); 899 ss << ", ["; 900 printReg(ss, urb); 901 ss << ", "; 902 ccprintf(ss, "#%d", imm); 903 ss << "]"; 904 return ss.str(); 905} 906 907} 908