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