1 //===-- PerfectShuffle.cpp - Perfect Shuffle Generator --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file computes an optimal sequence of instructions for doing all shuffles 10 // of two 4-element vectors. With a release build and when configured to emit 11 // an altivec instruction table, this takes about 30s to run on a 2.7Ghz 12 // PowerPC G5. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include <cassert> 17 #include <cstdlib> 18 #include <iomanip> 19 #include <iostream> 20 #include <vector> 21 22 #define GENERATE_NEON 23 #define GENERATE_NEON_INS 24 25 struct Operator; 26 27 // Masks are 4-nibble hex numbers. Values 0-7 in any nibble means that it takes 28 // an element from that value of the input vectors. A value of 8 means the 29 // entry is undefined. 30 31 // Mask manipulation functions. 32 static inline unsigned short MakeMask(unsigned V0, unsigned V1, 33 unsigned V2, unsigned V3) { 34 return (V0 << (3*4)) | (V1 << (2*4)) | (V2 << (1*4)) | (V3 << (0*4)); 35 } 36 37 /// getMaskElt - Return element N of the specified mask. 38 static unsigned getMaskElt(unsigned Mask, unsigned Elt) { 39 return (Mask >> ((3-Elt)*4)) & 0xF; 40 } 41 42 static unsigned setMaskElt(unsigned Mask, unsigned Elt, unsigned NewVal) { 43 unsigned FieldShift = ((3-Elt)*4); 44 return (Mask & ~(0xF << FieldShift)) | (NewVal << FieldShift); 45 } 46 47 // Reject elements where the values are 9-15. 48 static bool isValidMask(unsigned short Mask) { 49 unsigned short UndefBits = Mask & 0x8888; 50 return (Mask & ((UndefBits >> 1)|(UndefBits>>2)|(UndefBits>>3))) == 0; 51 } 52 53 /// hasUndefElements - Return true if any of the elements in the mask are undefs 54 /// 55 static bool hasUndefElements(unsigned short Mask) { 56 return (Mask & 0x8888) != 0; 57 } 58 59 /// isOnlyLHSMask - Return true if this mask only refers to its LHS, not 60 /// including undef values.. 61 static bool isOnlyLHSMask(unsigned short Mask) { 62 return (Mask & 0x4444) == 0; 63 } 64 65 /// getLHSOnlyMask - Given a mask that refers to its LHS and RHS, modify it to 66 /// refer to the LHS only (for when one argument value is passed into the same 67 /// function twice). 68 #if 0 69 static unsigned short getLHSOnlyMask(unsigned short Mask) { 70 return Mask & 0xBBBB; // Keep only LHS and Undefs. 71 } 72 #endif 73 74 /// getCompressedMask - Turn a 16-bit uncompressed mask (where each elt uses 4 75 /// bits) into a compressed 13-bit mask, where each elt is multiplied by 9. 76 static unsigned getCompressedMask(unsigned short Mask) { 77 return getMaskElt(Mask, 0)*9*9*9 + getMaskElt(Mask, 1)*9*9 + 78 getMaskElt(Mask, 2)*9 + getMaskElt(Mask, 3); 79 } 80 81 static void PrintMask(unsigned i, std::ostream &OS) { 82 OS << "<" << (char)(getMaskElt(i, 0) == 8 ? 'u' : ('0'+getMaskElt(i, 0))) 83 << "," << (char)(getMaskElt(i, 1) == 8 ? 'u' : ('0'+getMaskElt(i, 1))) 84 << "," << (char)(getMaskElt(i, 2) == 8 ? 'u' : ('0'+getMaskElt(i, 2))) 85 << "," << (char)(getMaskElt(i, 3) == 8 ? 'u' : ('0'+getMaskElt(i, 3))) 86 << ">"; 87 } 88 89 /// ShuffleVal - This represents a shufflevector operation. 90 struct ShuffleVal { 91 Operator *Op; // The Operation used to generate this value. 92 unsigned Cost; // Number of instrs used to generate this value. 93 unsigned short Arg0, Arg1; // Input operands for this value. 94 95 ShuffleVal() : Cost(1000000) {} 96 }; 97 98 99 /// ShufTab - This is the actual shuffle table that we are trying to generate. 100 /// 101 static ShuffleVal ShufTab[65536]; 102 103 /// TheOperators - All of the operators that this target supports. 104 static std::vector<Operator*> TheOperators; 105 106 /// Operator - This is a vector operation that is available for use. 107 struct Operator { 108 const char *Name; 109 unsigned short ShuffleMask; 110 unsigned short OpNum; 111 unsigned Cost; 112 113 Operator(unsigned short shufflemask, const char *name, unsigned opnum, 114 unsigned cost = 1) 115 : Name(name), ShuffleMask(shufflemask), OpNum(opnum),Cost(cost) { 116 TheOperators.push_back(this); 117 } 118 ~Operator() { 119 assert(TheOperators.back() == this); 120 TheOperators.pop_back(); 121 } 122 123 bool isOnlyLHSOperator() const { 124 return isOnlyLHSMask(ShuffleMask); 125 } 126 127 const char *getName() const { return Name; } 128 unsigned getCost() const { return Cost; } 129 130 unsigned short getTransformedMask(unsigned short LHSMask, unsigned RHSMask) { 131 // Extract the elements from LHSMask and RHSMask, as appropriate. 132 unsigned Result = 0; 133 for (unsigned i = 0; i != 4; ++i) { 134 unsigned SrcElt = (ShuffleMask >> (4*i)) & 0xF; 135 unsigned ResElt; 136 if (SrcElt < 4) 137 ResElt = getMaskElt(LHSMask, SrcElt); 138 else if (SrcElt < 8) 139 ResElt = getMaskElt(RHSMask, SrcElt-4); 140 else { 141 assert(SrcElt == 8 && "Bad src elt!"); 142 ResElt = 8; 143 } 144 Result |= ResElt << (4*i); 145 } 146 return Result; 147 } 148 }; 149 150 #ifdef GENERATE_NEON_INS 151 // Special case "insert" op identifier used below 152 static Operator InsOp(0, "ins", 15, 1); 153 #endif 154 155 static const char *getZeroCostOpName(unsigned short Op) { 156 if (ShufTab[Op].Arg0 == 0x0123) 157 return "LHS"; 158 else if (ShufTab[Op].Arg0 == 0x4567) 159 return "RHS"; 160 else { 161 assert(0 && "bad zero cost operation"); 162 abort(); 163 } 164 } 165 166 static void PrintOperation(unsigned ValNo, unsigned short Vals[]) { 167 unsigned short ThisOp = Vals[ValNo]; 168 std::cerr << "t" << ValNo; 169 PrintMask(ThisOp, std::cerr); 170 std::cerr << " = " << ShufTab[ThisOp].Op->getName() << "("; 171 172 if (ShufTab[ShufTab[ThisOp].Arg0].Cost == 0) { 173 std::cerr << getZeroCostOpName(ShufTab[ThisOp].Arg0); 174 PrintMask(ShufTab[ThisOp].Arg0, std::cerr); 175 } else { 176 // Figure out what tmp # it is. 177 for (unsigned i = 0; ; ++i) 178 if (Vals[i] == ShufTab[ThisOp].Arg0) { 179 std::cerr << "t" << i; 180 break; 181 } 182 } 183 184 #ifdef GENERATE_NEON_INS 185 if (ShufTab[ThisOp].Op == &InsOp) { 186 std::cerr << ", lane " << ShufTab[ThisOp].Arg1; 187 } else 188 #endif 189 if (!ShufTab[Vals[ValNo]].Op->isOnlyLHSOperator()) { 190 std::cerr << ", "; 191 if (ShufTab[ShufTab[ThisOp].Arg1].Cost == 0) { 192 std::cerr << getZeroCostOpName(ShufTab[ThisOp].Arg1); 193 PrintMask(ShufTab[ThisOp].Arg1, std::cerr); 194 } else { 195 // Figure out what tmp # it is. 196 for (unsigned i = 0; ; ++i) 197 if (Vals[i] == ShufTab[ThisOp].Arg1) { 198 std::cerr << "t" << i; 199 break; 200 } 201 } 202 } 203 std::cerr << ") "; 204 } 205 206 static unsigned getNumEntered() { 207 unsigned Count = 0; 208 for (unsigned i = 0; i != 65536; ++i) 209 Count += ShufTab[i].Cost < 100; 210 return Count; 211 } 212 213 static void EvaluateOps(unsigned short Elt, unsigned short Vals[], 214 unsigned &NumVals) { 215 if (ShufTab[Elt].Cost == 0) return; 216 #ifdef GENERATE_NEON_INS 217 if (ShufTab[Elt].Op == &InsOp) { 218 EvaluateOps(ShufTab[Elt].Arg0, Vals, NumVals); 219 Vals[NumVals++] = Elt; 220 return; 221 } 222 #endif 223 224 // If this value has already been evaluated, it is free. FIXME: match undefs. 225 for (unsigned i = 0, e = NumVals; i != e; ++i) 226 if (Vals[i] == Elt) return; 227 228 // Otherwise, get the operands of the value, then add it. 229 unsigned Arg0 = ShufTab[Elt].Arg0, Arg1 = ShufTab[Elt].Arg1; 230 if (ShufTab[Arg0].Cost) 231 EvaluateOps(Arg0, Vals, NumVals); 232 if (Arg0 != Arg1 && ShufTab[Arg1].Cost) 233 EvaluateOps(Arg1, Vals, NumVals); 234 235 Vals[NumVals++] = Elt; 236 } 237 238 239 int main() { 240 // Seed the table with accesses to the LHS and RHS. 241 ShufTab[0x0123].Cost = 0; 242 ShufTab[0x0123].Op = nullptr; 243 ShufTab[0x0123].Arg0 = 0x0123; 244 ShufTab[0x4567].Cost = 0; 245 ShufTab[0x4567].Op = nullptr; 246 ShufTab[0x4567].Arg0 = 0x4567; 247 248 // Seed the first-level of shuffles, shuffles whose inputs are the input to 249 // the vectorshuffle operation. 250 bool MadeChange = true; 251 unsigned OpCount = 0; 252 while (MadeChange) { 253 MadeChange = false; 254 ++OpCount; 255 std::cerr << "Starting iteration #" << OpCount << " with " 256 << getNumEntered() << " entries established.\n"; 257 258 // Scan the table for two reasons: First, compute the maximum cost of any 259 // operation left in the table. Second, make sure that values with undefs 260 // have the cheapest alternative that they match. 261 unsigned MaxCost = ShufTab[0].Cost; 262 for (unsigned i = 1; i != 0x8889; ++i) { 263 if (!isValidMask(i)) continue; 264 if (ShufTab[i].Cost > MaxCost) 265 MaxCost = ShufTab[i].Cost; 266 267 // If this value has an undef, make it be computed the cheapest possible 268 // way of any of the things that it matches. 269 if (hasUndefElements(i)) { 270 // This code is a little bit tricky, so here's the idea: consider some 271 // permutation, like 7u4u. To compute the lowest cost for 7u4u, we 272 // need to take the minimum cost of all of 7[0-8]4[0-8], 81 entries. If 273 // there are 3 undefs, the number rises to 729 entries we have to scan, 274 // and for the 4 undef case, we have to scan the whole table. 275 // 276 // Instead of doing this huge amount of scanning, we process the table 277 // entries *in order*, and use the fact that 'u' is 8, larger than any 278 // valid index. Given an entry like 7u4u then, we only need to scan 279 // 7[0-7]4u - 8 entries. We can get away with this, because we already 280 // know that each of 704u, 714u, 724u, etc contain the minimum value of 281 // all of the 704[0-8], 714[0-8] and 724[0-8] entries respectively. 282 unsigned UndefIdx; 283 if (i & 0x8000) 284 UndefIdx = 0; 285 else if (i & 0x0800) 286 UndefIdx = 1; 287 else if (i & 0x0080) 288 UndefIdx = 2; 289 else if (i & 0x0008) 290 UndefIdx = 3; 291 else 292 abort(); 293 294 unsigned MinVal = i; 295 unsigned MinCost = ShufTab[i].Cost; 296 297 // Scan the 8 entries. 298 for (unsigned j = 0; j != 8; ++j) { 299 unsigned NewElt = setMaskElt(i, UndefIdx, j); 300 if (ShufTab[NewElt].Cost < MinCost) { 301 MinCost = ShufTab[NewElt].Cost; 302 MinVal = NewElt; 303 } 304 } 305 306 // If we found something cheaper than what was here before, use it. 307 if (i != MinVal) { 308 MadeChange = true; 309 ShufTab[i] = ShufTab[MinVal]; 310 } 311 } 312 #ifdef GENERATE_NEON_INS 313 else { 314 // Similarly, if we take the mask (eg 3,6,1,0) and take the cost with 315 // undef for each lane (eg u,6,1,0 or 3,u,1,0 etc), we can use a single 316 // lane insert to fixup the result. 317 for (unsigned LaneIdx = 0; LaneIdx < 4; LaneIdx++) { 318 if (getMaskElt(i, LaneIdx) == 8) 319 continue; 320 unsigned NewElt = setMaskElt(i, LaneIdx, 8); 321 if (ShufTab[NewElt].Cost + 1 < ShufTab[i].Cost) { 322 MadeChange = true; 323 ShufTab[i].Cost = ShufTab[NewElt].Cost + 1; 324 ShufTab[i].Op = &InsOp; 325 ShufTab[i].Arg0 = NewElt; 326 ShufTab[i].Arg1 = LaneIdx; 327 } 328 } 329 } 330 #endif 331 } 332 333 for (unsigned LHS = 0; LHS != 0x8889; ++LHS) { 334 if (!isValidMask(LHS)) continue; 335 if (ShufTab[LHS].Cost > 1000) continue; 336 337 // If nothing involving this operand could possibly be cheaper than what 338 // we already have, don't consider it. 339 if (ShufTab[LHS].Cost + 1 >= MaxCost) 340 continue; 341 342 for (unsigned opnum = 0, e = TheOperators.size(); opnum != e; ++opnum) { 343 Operator *Op = TheOperators[opnum]; 344 #ifdef GENERATE_NEON_INS 345 if (Op == &InsOp) 346 continue; 347 #endif 348 349 // Evaluate op(LHS,LHS) 350 unsigned ResultMask = Op->getTransformedMask(LHS, LHS); 351 352 unsigned Cost = ShufTab[LHS].Cost + Op->getCost(); 353 if (Cost < ShufTab[ResultMask].Cost) { 354 ShufTab[ResultMask].Cost = Cost; 355 ShufTab[ResultMask].Op = Op; 356 ShufTab[ResultMask].Arg0 = LHS; 357 ShufTab[ResultMask].Arg1 = LHS; 358 MadeChange = true; 359 } 360 361 // If this is a two input instruction, include the op(x,y) cases. If 362 // this is a one input instruction, skip this. 363 if (Op->isOnlyLHSOperator()) continue; 364 365 for (unsigned RHS = 0; RHS != 0x8889; ++RHS) { 366 if (!isValidMask(RHS)) continue; 367 if (ShufTab[RHS].Cost > 1000) continue; 368 369 // If nothing involving this operand could possibly be cheaper than 370 // what we already have, don't consider it. 371 if (ShufTab[RHS].Cost + 1 >= MaxCost) 372 continue; 373 374 375 // Evaluate op(LHS,RHS) 376 unsigned ResultMask = Op->getTransformedMask(LHS, RHS); 377 378 if (ShufTab[ResultMask].Cost <= OpCount || 379 ShufTab[ResultMask].Cost <= ShufTab[LHS].Cost || 380 ShufTab[ResultMask].Cost <= ShufTab[RHS].Cost) 381 continue; 382 383 // Figure out the cost to evaluate this, knowing that CSE's only need 384 // to be evaluated once. 385 unsigned short Vals[30]; 386 unsigned NumVals = 0; 387 EvaluateOps(LHS, Vals, NumVals); 388 EvaluateOps(RHS, Vals, NumVals); 389 390 unsigned Cost = NumVals + Op->getCost(); 391 if (Cost < ShufTab[ResultMask].Cost) { 392 ShufTab[ResultMask].Cost = Cost; 393 ShufTab[ResultMask].Op = Op; 394 ShufTab[ResultMask].Arg0 = LHS; 395 ShufTab[ResultMask].Arg1 = RHS; 396 MadeChange = true; 397 } 398 } 399 } 400 } 401 } 402 403 std::cerr << "Finished Table has " << getNumEntered() 404 << " entries established.\n"; 405 406 unsigned CostArray[10] = { 0 }; 407 408 // Compute a cost histogram. 409 for (unsigned i = 0; i != 65536; ++i) { 410 if (!isValidMask(i)) continue; 411 if (ShufTab[i].Cost > 9) 412 ++CostArray[9]; 413 else 414 ++CostArray[ShufTab[i].Cost]; 415 } 416 417 for (unsigned i = 0; i != 9; ++i) 418 if (CostArray[i]) 419 std::cout << "// " << CostArray[i] << " entries have cost " << i << "\n"; 420 if (CostArray[9]) 421 std::cout << "// " << CostArray[9] << " entries have higher cost!\n"; 422 423 424 // Build up the table to emit. 425 std::cout << "\n// This table is 6561*4 = 26244 bytes in size.\n"; 426 std::cout << "static const unsigned PerfectShuffleTable[6561+1] = {\n"; 427 428 for (unsigned i = 0; i != 0x8889; ++i) { 429 if (!isValidMask(i)) continue; 430 431 // CostSat - The cost of this operation saturated to two bits. 432 unsigned CostSat = ShufTab[i].Cost; 433 if (CostSat > 4) CostSat = 4; 434 if (CostSat == 0) CostSat = 1; 435 --CostSat; // Cost is now between 0-3. 436 437 unsigned OpNum = ShufTab[i].Op ? ShufTab[i].Op->OpNum : 0; 438 assert(OpNum < 16 && "Too few bits to encode operation!"); 439 440 unsigned LHS = getCompressedMask(ShufTab[i].Arg0); 441 unsigned RHS = getCompressedMask(ShufTab[i].Arg1); 442 443 // Encode this as 2 bits of saturated cost, 4 bits of opcodes, 13 bits of 444 // LHS, and 13 bits of RHS = 32 bits. 445 unsigned Val = (CostSat << 30) | (OpNum << 26) | (LHS << 13) | RHS; 446 447 std::cout << " " << std::setw(10) << Val << "U, // "; 448 PrintMask(i, std::cout); 449 std::cout << ": Cost " << ShufTab[i].Cost; 450 std::cout << " " << (ShufTab[i].Op ? ShufTab[i].Op->getName() : "copy"); 451 std::cout << " "; 452 if (ShufTab[ShufTab[i].Arg0].Cost == 0) { 453 std::cout << getZeroCostOpName(ShufTab[i].Arg0); 454 } else { 455 PrintMask(ShufTab[i].Arg0, std::cout); 456 } 457 458 if (ShufTab[i].Op && !ShufTab[i].Op->isOnlyLHSOperator()) { 459 std::cout << ", "; 460 if (ShufTab[ShufTab[i].Arg1].Cost == 0) { 461 std::cout << getZeroCostOpName(ShufTab[i].Arg1); 462 } else { 463 PrintMask(ShufTab[i].Arg1, std::cout); 464 } 465 } 466 #ifdef GENERATE_NEON_INS 467 else if (ShufTab[i].Op == &InsOp) { 468 std::cout << ", lane " << ShufTab[i].Arg1; 469 } 470 #endif 471 472 std::cout << "\n"; 473 } 474 std::cout << " 0\n};\n"; 475 476 if (false) { 477 // Print out the table. 478 for (unsigned i = 0; i != 0x8889; ++i) { 479 if (!isValidMask(i)) continue; 480 if (ShufTab[i].Cost < 1000) { 481 PrintMask(i, std::cerr); 482 std::cerr << " - Cost " << ShufTab[i].Cost << " - "; 483 484 unsigned short Vals[30]; 485 unsigned NumVals = 0; 486 EvaluateOps(i, Vals, NumVals); 487 488 for (unsigned j = 0, e = NumVals; j != e; ++j) 489 PrintOperation(j, Vals); 490 std::cerr << "\n"; 491 } 492 } 493 } 494 } 495 496 497 #ifdef GENERATE_ALTIVEC 498 499 ///===---------------------------------------------------------------------===// 500 /// The altivec instruction definitions. This is the altivec-specific part of 501 /// this file. 502 ///===---------------------------------------------------------------------===// 503 504 // Note that the opcode numbers here must match those in the PPC backend. 505 enum { 506 OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3> 507 OP_VMRGHW, 508 OP_VMRGLW, 509 OP_VSPLTISW0, 510 OP_VSPLTISW1, 511 OP_VSPLTISW2, 512 OP_VSPLTISW3, 513 OP_VSLDOI4, 514 OP_VSLDOI8, 515 OP_VSLDOI12 516 }; 517 518 struct vmrghw : public Operator { 519 vmrghw() : Operator(0x0415, "vmrghw", OP_VMRGHW) {} 520 } the_vmrghw; 521 522 struct vmrglw : public Operator { 523 vmrglw() : Operator(0x2637, "vmrglw", OP_VMRGLW) {} 524 } the_vmrglw; 525 526 template<unsigned Elt> 527 struct vspltisw : public Operator { 528 vspltisw(const char *N, unsigned Opc) 529 : Operator(MakeMask(Elt, Elt, Elt, Elt), N, Opc) {} 530 }; 531 532 vspltisw<0> the_vspltisw0("vspltisw0", OP_VSPLTISW0); 533 vspltisw<1> the_vspltisw1("vspltisw1", OP_VSPLTISW1); 534 vspltisw<2> the_vspltisw2("vspltisw2", OP_VSPLTISW2); 535 vspltisw<3> the_vspltisw3("vspltisw3", OP_VSPLTISW3); 536 537 template<unsigned N> 538 struct vsldoi : public Operator { 539 vsldoi(const char *Name, unsigned Opc) 540 : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), Name, Opc) { 541 } 542 }; 543 544 vsldoi<1> the_vsldoi1("vsldoi4" , OP_VSLDOI4); 545 vsldoi<2> the_vsldoi2("vsldoi8" , OP_VSLDOI8); 546 vsldoi<3> the_vsldoi3("vsldoi12", OP_VSLDOI12); 547 548 #endif 549 550 #ifdef GENERATE_NEON 551 enum { 552 OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3> 553 OP_VREV, 554 OP_VDUP0, 555 OP_VDUP1, 556 OP_VDUP2, 557 OP_VDUP3, 558 OP_VEXT1, 559 OP_VEXT2, 560 OP_VEXT3, 561 OP_VUZPL, // VUZP, left result 562 OP_VUZPR, // VUZP, right result 563 OP_VZIPL, // VZIP, left result 564 OP_VZIPR, // VZIP, right result 565 OP_VTRNL, // VTRN, left result 566 OP_VTRNR // VTRN, right result 567 }; 568 569 struct vrev : public Operator { 570 vrev() : Operator(0x1032, "vrev", OP_VREV) {} 571 } the_vrev; 572 573 template<unsigned Elt> 574 struct vdup : public Operator { 575 vdup(const char *N, unsigned Opc) 576 : Operator(MakeMask(Elt, Elt, Elt, Elt), N, Opc) {} 577 }; 578 579 vdup<0> the_vdup0("vdup0", OP_VDUP0); 580 vdup<1> the_vdup1("vdup1", OP_VDUP1); 581 vdup<2> the_vdup2("vdup2", OP_VDUP2); 582 vdup<3> the_vdup3("vdup3", OP_VDUP3); 583 584 template<unsigned N> 585 struct vext : public Operator { 586 vext(const char *Name, unsigned Opc) 587 : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), Name, Opc) { 588 } 589 }; 590 591 vext<1> the_vext1("vext1", OP_VEXT1); 592 vext<2> the_vext2("vext2", OP_VEXT2); 593 vext<3> the_vext3("vext3", OP_VEXT3); 594 595 struct vuzpl : public Operator { 596 vuzpl() : Operator(0x0246, "vuzpl", OP_VUZPL, 1) {} 597 } the_vuzpl; 598 599 struct vuzpr : public Operator { 600 vuzpr() : Operator(0x1357, "vuzpr", OP_VUZPR, 1) {} 601 } the_vuzpr; 602 603 struct vzipl : public Operator { 604 vzipl() : Operator(0x0415, "vzipl", OP_VZIPL, 1) {} 605 } the_vzipl; 606 607 struct vzipr : public Operator { 608 vzipr() : Operator(0x2637, "vzipr", OP_VZIPR, 1) {} 609 } the_vzipr; 610 611 struct vtrnl : public Operator { 612 vtrnl() : Operator(0x0426, "vtrnl", OP_VTRNL, 1) {} 613 } the_vtrnl; 614 615 struct vtrnr : public Operator { 616 vtrnr() : Operator(0x1537, "vtrnr", OP_VTRNR, 1) {} 617 } the_vtrnr; 618 619 #endif 620