1 /* 2 * Copyright (c) 2017-2020, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** \file 30 * \brief Concrete classes for interpreter instructions. 31 * 32 * Note: this header should only be included in files which need to deal with 33 * the details of actual instructions. It is expected that most will only 34 * require access to the RoseInstruction API exposed in rose_build_program.h 35 */ 36 37 #ifndef ROSE_BUILD_INSTRUCTIONS_H 38 #define ROSE_BUILD_INSTRUCTIONS_H 39 40 #include "rose_build_lookaround.h" 41 #include "rose_build_program.h" 42 #include "util/hash.h" 43 #include "util/verify_types.h" 44 45 namespace ue2 { 46 47 /** 48 * \brief Abstract base class representing a single Rose instruction. 49 */ 50 class RoseInstruction { 51 public: 52 virtual ~RoseInstruction(); 53 54 /** \brief Opcode used for the instruction in the bytecode. */ 55 virtual RoseInstructionCode code() const = 0; 56 57 /** 58 * \brief Simple hash used for program equivalence. 59 * 60 * Note that pointers (jumps, for example) should not be used when 61 * calculating the hash: they will be converted to instruction offsets when 62 * compared later. 63 */ 64 virtual size_t hash() const = 0; 65 66 /** \brief Length of the bytecode instruction in bytes. */ 67 virtual size_t byte_length() const = 0; 68 69 using OffsetMap = std::unordered_map<const RoseInstruction *, u32>; 70 71 /** 72 * \brief Writes a concrete implementation of this instruction. 73 * 74 * Other data that this instruction depends on is written directly into the 75 * blob, while the instruction structure itself (of size given by 76 * the byte_length() function) is written to dest. 77 */ 78 virtual void write(void *dest, RoseEngineBlob &blob, 79 const OffsetMap &offset_map) const = 0; 80 81 /** 82 * \brief Update a target pointer. 83 * 84 * If this instruction contains any reference to the old target, replace it 85 * with the new one. 86 */ 87 virtual void update_target(const RoseInstruction *old_target, 88 const RoseInstruction *new_target) = 0; 89 90 /** 91 * \brief True if these instructions are equivalent within their own 92 * programs. 93 * 94 * Checks that any pointers to other instructions point to the same 95 * offsets. 96 */ equiv(const RoseInstruction & other,const OffsetMap & offsets,const OffsetMap & other_offsets)97 bool equiv(const RoseInstruction &other, const OffsetMap &offsets, 98 const OffsetMap &other_offsets) const { 99 return equiv_impl(other, offsets, other_offsets); 100 } 101 102 private: 103 virtual bool equiv_impl(const RoseInstruction &other, 104 const OffsetMap &offsets, 105 const OffsetMap &other_offsets) const = 0; 106 }; 107 108 /** 109 * \brief Templated implementation class to handle boring boilerplate code. 110 */ 111 template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType> 112 class RoseInstrBase : public RoseInstruction { 113 protected: 114 static constexpr RoseInstructionCode opcode = Opcode; 115 using impl_type = ImplType; 116 117 public: code()118 RoseInstructionCode code() const override { return opcode; } 119 byte_length()120 size_t byte_length() const override { 121 return sizeof(impl_type); 122 } 123 124 /** 125 * Note: this implementation simply zeroes the destination region and 126 * writes in the correct opcode. This is sufficient for trivial 127 * instructions, but instructions with data members will want to override 128 * it. 129 */ write(void * dest,RoseEngineBlob &,const RoseInstruction::OffsetMap &)130 void write(void *dest, RoseEngineBlob &, 131 const RoseInstruction::OffsetMap &) const override { 132 assert(dest != nullptr); 133 assert(ISALIGNED_N(dest, ROSE_INSTR_MIN_ALIGN)); 134 135 impl_type *inst = static_cast<impl_type *>(dest); 136 memset(inst, 0, sizeof(impl_type)); 137 inst->code = verify_u8(opcode); 138 } 139 140 private: equiv_impl(const RoseInstruction & other,const OffsetMap & offsets,const OffsetMap & other_offsets)141 bool equiv_impl(const RoseInstruction &other, const OffsetMap &offsets, 142 const OffsetMap &other_offsets) const override { 143 const auto *ri_that = dynamic_cast<const RoseInstrType *>(&other); 144 if (!ri_that) { 145 return false; 146 } 147 const auto *ri_this = dynamic_cast<const RoseInstrType *>(this); 148 assert(ri_this); 149 return ri_this->equiv_to(*ri_that, offsets, other_offsets); 150 } 151 }; 152 153 template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType> 154 constexpr RoseInstructionCode 155 RoseInstrBase<Opcode, ImplType, RoseInstrType>::opcode; 156 157 /** 158 * \brief Refinement of RoseInstrBase to use for instructions that have 159 * just a single target member, called "target". 160 */ 161 template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType> 162 class RoseInstrBaseOneTarget 163 : public RoseInstrBase<Opcode, ImplType, RoseInstrType> { 164 public: update_target(const RoseInstruction * old_target,const RoseInstruction * new_target)165 void update_target(const RoseInstruction *old_target, 166 const RoseInstruction *new_target) override { 167 RoseInstrType *ri = dynamic_cast<RoseInstrType *>(this); 168 assert(ri); 169 if (ri->target == old_target) { 170 ri->target = new_target; 171 } 172 } 173 }; 174 175 /** 176 * \brief Refinement of RoseInstrBase to use for instructions that have no 177 * targets. 178 */ 179 template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType> 180 class RoseInstrBaseNoTargets 181 : public RoseInstrBase<Opcode, ImplType, RoseInstrType> { 182 public: update_target(const RoseInstruction *,const RoseInstruction *)183 void update_target(const RoseInstruction *, 184 const RoseInstruction *) override {} 185 }; 186 187 /** 188 * \brief Refinement of RoseInstrBaseNoTargets to use for instructions that 189 * have no members at all, just an opcode. 190 */ 191 template<RoseInstructionCode Opcode, class ImplType, class RoseInstrType> 192 class RoseInstrBaseTrivial 193 : public RoseInstrBaseNoTargets<Opcode, ImplType, RoseInstrType> { 194 public: 195 virtual bool operator==(const RoseInstrType &) const { return true; } 196 hash()197 size_t hash() const override { 198 return hash_all(Opcode); 199 } 200 equiv_to(const RoseInstrType &,const RoseInstruction::OffsetMap &,const RoseInstruction::OffsetMap &)201 bool equiv_to(const RoseInstrType &, const RoseInstruction::OffsetMap &, 202 const RoseInstruction::OffsetMap &) const { 203 return true; 204 } 205 }; 206 207 //// 208 //// Concrete implementation classes start here. 209 //// 210 211 class RoseInstrAnchoredDelay 212 : public RoseInstrBaseOneTarget<ROSE_INSTR_ANCHORED_DELAY, 213 ROSE_STRUCT_ANCHORED_DELAY, 214 RoseInstrAnchoredDelay> { 215 public: 216 rose_group groups; 217 u32 anch_id; 218 const RoseInstruction *target; 219 RoseInstrAnchoredDelay(rose_group groups_in,u32 anch_id_in,const RoseInstruction * target_in)220 RoseInstrAnchoredDelay(rose_group groups_in, u32 anch_id_in, 221 const RoseInstruction *target_in) 222 : groups(groups_in), anch_id(anch_id_in), target(target_in) {} 223 224 bool operator==(const RoseInstrAnchoredDelay &ri) const { 225 return groups == ri.groups && anch_id == ri.anch_id 226 && target == ri.target; 227 } 228 hash()229 size_t hash() const override { 230 return hash_all(opcode, groups, anch_id); 231 } 232 233 void write(void *dest, RoseEngineBlob &blob, 234 const OffsetMap &offset_map) const override; 235 equiv_to(const RoseInstrAnchoredDelay & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)236 bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets, 237 const OffsetMap &other_offsets) const { 238 return groups == ri.groups && anch_id == ri.anch_id 239 && offsets.at(target) == other_offsets.at(ri.target); 240 } 241 }; 242 243 class RoseInstrCheckLitEarly 244 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LIT_EARLY, 245 ROSE_STRUCT_CHECK_LIT_EARLY, 246 RoseInstrCheckLitEarly> { 247 public: 248 u32 min_offset; 249 const RoseInstruction *target; 250 RoseInstrCheckLitEarly(u32 min_offset_in,const RoseInstruction * target_in)251 RoseInstrCheckLitEarly(u32 min_offset_in, const RoseInstruction *target_in) 252 : min_offset(min_offset_in), target(target_in) {} 253 254 bool operator==(const RoseInstrCheckLitEarly &ri) const { 255 return min_offset == ri.min_offset && target == ri.target; 256 } 257 hash()258 size_t hash() const override { 259 return hash_all(opcode, min_offset); 260 } 261 262 void write(void *dest, RoseEngineBlob &blob, 263 const OffsetMap &offset_map) const override; 264 equiv_to(const RoseInstrCheckLitEarly & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)265 bool equiv_to(const RoseInstrCheckLitEarly &ri, const OffsetMap &offsets, 266 const OffsetMap &other_offsets) const { 267 return min_offset == ri.min_offset && 268 offsets.at(target) == other_offsets.at(ri.target); 269 } 270 }; 271 272 class RoseInstrCheckGroups 273 : public RoseInstrBaseNoTargets<ROSE_INSTR_CHECK_GROUPS, 274 ROSE_STRUCT_CHECK_GROUPS, 275 RoseInstrCheckGroups> { 276 public: 277 rose_group groups; 278 RoseInstrCheckGroups(rose_group groups_in)279 explicit RoseInstrCheckGroups(rose_group groups_in) : groups(groups_in) {} 280 281 bool operator==(const RoseInstrCheckGroups &ri) const { 282 return groups == ri.groups; 283 } 284 hash()285 size_t hash() const override { 286 return hash_all(opcode, groups); 287 } 288 289 void write(void *dest, RoseEngineBlob &blob, 290 const OffsetMap &offset_map) const override; 291 equiv_to(const RoseInstrCheckGroups & ri,const OffsetMap &,const OffsetMap &)292 bool equiv_to(const RoseInstrCheckGroups &ri, const OffsetMap &, 293 const OffsetMap &) const { 294 return groups == ri.groups; 295 } 296 }; 297 298 class RoseInstrCheckOnlyEod 299 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_ONLY_EOD, 300 ROSE_STRUCT_CHECK_ONLY_EOD, 301 RoseInstrCheckOnlyEod> { 302 public: 303 const RoseInstruction *target; 304 RoseInstrCheckOnlyEod(const RoseInstruction * target_in)305 explicit RoseInstrCheckOnlyEod(const RoseInstruction *target_in) 306 : target(target_in) {} 307 308 bool operator==(const RoseInstrCheckOnlyEod &ri) const { 309 return target == ri.target; 310 } 311 hash()312 size_t hash() const override { 313 return hash_all(opcode); 314 } 315 316 void write(void *dest, RoseEngineBlob &blob, 317 const OffsetMap &offset_map) const override; 318 equiv_to(const RoseInstrCheckOnlyEod & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)319 bool equiv_to(const RoseInstrCheckOnlyEod &ri, const OffsetMap &offsets, 320 const OffsetMap &other_offsets) const { 321 return offsets.at(target) == other_offsets.at(ri.target); 322 } 323 }; 324 325 class RoseInstrCheckBounds 326 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BOUNDS, 327 ROSE_STRUCT_CHECK_BOUNDS, 328 RoseInstrCheckBounds> { 329 public: 330 u64a min_bound; 331 u64a max_bound; 332 const RoseInstruction *target; 333 RoseInstrCheckBounds(u64a min,u64a max,const RoseInstruction * target_in)334 RoseInstrCheckBounds(u64a min, u64a max, const RoseInstruction *target_in) 335 : min_bound(min), max_bound(max), target(target_in) {} 336 337 bool operator==(const RoseInstrCheckBounds &ri) const { 338 return min_bound == ri.min_bound && max_bound == ri.max_bound && 339 target == ri.target; 340 } 341 hash()342 size_t hash() const override { 343 return hash_all(opcode, min_bound, max_bound); 344 } 345 346 void write(void *dest, RoseEngineBlob &blob, 347 const OffsetMap &offset_map) const override; 348 equiv_to(const RoseInstrCheckBounds & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)349 bool equiv_to(const RoseInstrCheckBounds &ri, const OffsetMap &offsets, 350 const OffsetMap &other_offsets) const { 351 return min_bound == ri.min_bound && max_bound == ri.max_bound && 352 offsets.at(target) == other_offsets.at(ri.target); 353 } 354 }; 355 356 class RoseInstrCheckNotHandled 357 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_NOT_HANDLED, 358 ROSE_STRUCT_CHECK_NOT_HANDLED, 359 RoseInstrCheckNotHandled> { 360 public: 361 u32 key; 362 const RoseInstruction *target; 363 RoseInstrCheckNotHandled(u32 key_in,const RoseInstruction * target_in)364 RoseInstrCheckNotHandled(u32 key_in, const RoseInstruction *target_in) 365 : key(key_in), target(target_in) {} 366 367 bool operator==(const RoseInstrCheckNotHandled &ri) const { 368 return key == ri.key && target == ri.target; 369 } 370 hash()371 size_t hash() const override { 372 return hash_all(opcode, key); 373 } 374 375 void write(void *dest, RoseEngineBlob &blob, 376 const OffsetMap &offset_map) const override; 377 equiv_to(const RoseInstrCheckNotHandled & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)378 bool equiv_to(const RoseInstrCheckNotHandled &ri, const OffsetMap &offsets, 379 const OffsetMap &other_offsets) const { 380 return key == ri.key && 381 offsets.at(target) == other_offsets.at(ri.target); 382 } 383 }; 384 385 class RoseInstrCheckSingleLookaround 386 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SINGLE_LOOKAROUND, 387 ROSE_STRUCT_CHECK_SINGLE_LOOKAROUND, 388 RoseInstrCheckSingleLookaround> { 389 public: 390 s8 offset; 391 CharReach reach; 392 const RoseInstruction *target; 393 RoseInstrCheckSingleLookaround(s8 offset_in,CharReach reach_in,const RoseInstruction * target_in)394 RoseInstrCheckSingleLookaround(s8 offset_in, CharReach reach_in, 395 const RoseInstruction *target_in) 396 : offset(offset_in), reach(std::move(reach_in)), target(target_in) {} 397 398 bool operator==(const RoseInstrCheckSingleLookaround &ri) const { 399 return offset == ri.offset && reach == ri.reach && target == ri.target; 400 } 401 hash()402 size_t hash() const override { 403 return hash_all(opcode, offset, reach); 404 } 405 406 void write(void *dest, RoseEngineBlob &blob, 407 const OffsetMap &offset_map) const override; 408 equiv_to(const RoseInstrCheckSingleLookaround & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)409 bool equiv_to(const RoseInstrCheckSingleLookaround &ri, 410 const OffsetMap &offsets, 411 const OffsetMap &other_offsets) const { 412 return offset == ri.offset && reach == ri.reach && 413 offsets.at(target) == other_offsets.at(ri.target); 414 } 415 }; 416 417 class RoseInstrCheckLookaround 418 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LOOKAROUND, 419 ROSE_STRUCT_CHECK_LOOKAROUND, 420 RoseInstrCheckLookaround> { 421 public: 422 std::vector<LookEntry> look; 423 const RoseInstruction *target; 424 RoseInstrCheckLookaround(std::vector<LookEntry> look_in,const RoseInstruction * target_in)425 RoseInstrCheckLookaround(std::vector<LookEntry> look_in, 426 const RoseInstruction *target_in) 427 : look(std::move(look_in)), target(target_in) {} 428 429 bool operator==(const RoseInstrCheckLookaround &ri) const { 430 return look == ri.look && target == ri.target; 431 } 432 hash()433 size_t hash() const override { 434 return hash_all(opcode, look); 435 } 436 437 void write(void *dest, RoseEngineBlob &blob, 438 const OffsetMap &offset_map) const override; 439 equiv_to(const RoseInstrCheckLookaround & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)440 bool equiv_to(const RoseInstrCheckLookaround &ri, const OffsetMap &offsets, 441 const OffsetMap &other_offsets) const { 442 return look == ri.look 443 && offsets.at(target) == other_offsets.at(ri.target); 444 } 445 }; 446 447 class RoseInstrCheckMask 448 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK, 449 ROSE_STRUCT_CHECK_MASK, 450 RoseInstrCheckMask> { 451 public: 452 u64a and_mask; 453 u64a cmp_mask; 454 u64a neg_mask; 455 s32 offset; 456 const RoseInstruction *target; 457 RoseInstrCheckMask(u64a and_mask_in,u64a cmp_mask_in,u64a neg_mask_in,s32 offset_in,const RoseInstruction * target_in)458 RoseInstrCheckMask(u64a and_mask_in, u64a cmp_mask_in, u64a neg_mask_in, 459 s32 offset_in, const RoseInstruction *target_in) 460 : and_mask(and_mask_in), cmp_mask(cmp_mask_in), neg_mask(neg_mask_in), 461 offset(offset_in), target(target_in) {} 462 463 bool operator==(const RoseInstrCheckMask &ri) const { 464 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 465 neg_mask == ri.neg_mask && offset == ri.offset && 466 target == ri.target; 467 } 468 hash()469 size_t hash() const override { 470 return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset); 471 } 472 473 void write(void *dest, RoseEngineBlob &blob, 474 const OffsetMap &offset_map) const override; 475 equiv_to(const RoseInstrCheckMask & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)476 bool equiv_to(const RoseInstrCheckMask &ri, const OffsetMap &offsets, 477 const OffsetMap &other_offsets) const { 478 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 479 neg_mask == ri.neg_mask && offset == ri.offset && 480 offsets.at(target) == other_offsets.at(ri.target); 481 } 482 }; 483 484 class RoseInstrCheckMask32 485 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK_32, 486 ROSE_STRUCT_CHECK_MASK_32, 487 RoseInstrCheckMask32> { 488 public: 489 std::array<u8, 32> and_mask; 490 std::array<u8, 32> cmp_mask; 491 u32 neg_mask; 492 s32 offset; 493 const RoseInstruction *target; 494 RoseInstrCheckMask32(std::array<u8,32> and_mask_in,std::array<u8,32> cmp_mask_in,u32 neg_mask_in,s32 offset_in,const RoseInstruction * target_in)495 RoseInstrCheckMask32(std::array<u8, 32> and_mask_in, 496 std::array<u8, 32> cmp_mask_in, u32 neg_mask_in, 497 s32 offset_in, const RoseInstruction *target_in) 498 : and_mask(std::move(and_mask_in)), cmp_mask(std::move(cmp_mask_in)), 499 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 500 501 bool operator==(const RoseInstrCheckMask32 &ri) const { 502 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 503 neg_mask == ri.neg_mask && offset == ri.offset && 504 target == ri.target; 505 } 506 hash()507 size_t hash() const override { 508 return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset); 509 } 510 511 void write(void *dest, RoseEngineBlob &blob, 512 const OffsetMap &offset_map) const override; 513 equiv_to(const RoseInstrCheckMask32 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)514 bool equiv_to(const RoseInstrCheckMask32 &ri, const OffsetMap &offsets, 515 const OffsetMap &other_offsets) const { 516 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 517 neg_mask == ri.neg_mask && offset == ri.offset && 518 offsets.at(target) == other_offsets.at(ri.target); 519 } 520 }; 521 522 class RoseInstrCheckMask64 523 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MASK_64, 524 ROSE_STRUCT_CHECK_MASK_64, 525 RoseInstrCheckMask64> { 526 public: 527 std::array<u8, 64> and_mask; 528 std::array<u8, 64> cmp_mask; 529 u64a neg_mask; 530 s32 offset; 531 const RoseInstruction *target; 532 RoseInstrCheckMask64(std::array<u8,64> and_mask_in,std::array<u8,64> cmp_mask_in,u64a neg_mask_in,s32 offset_in,const RoseInstruction * target_in)533 RoseInstrCheckMask64(std::array<u8, 64> and_mask_in, 534 std::array<u8, 64> cmp_mask_in, u64a neg_mask_in, 535 s32 offset_in, const RoseInstruction *target_in) 536 : and_mask(std::move(and_mask_in)), cmp_mask(std::move(cmp_mask_in)), 537 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 538 bool operator==(const RoseInstrCheckMask64 &ri) const { 539 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 540 neg_mask == ri.neg_mask && offset == ri.offset && 541 target == ri.target; 542 } 543 hash()544 size_t hash() const override { 545 return hash_all(opcode, and_mask, cmp_mask, neg_mask, offset); 546 } 547 548 void write(void *dest, RoseEngineBlob &blob, 549 const OffsetMap &offset_map) const override; 550 equiv_to(const RoseInstrCheckMask64 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)551 bool equiv_to(const RoseInstrCheckMask64 &ri, const OffsetMap &offsets, 552 const OffsetMap &other_offsets) const { 553 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 554 neg_mask == ri.neg_mask && offset == ri.offset && 555 offsets.at(target) == other_offsets.at(ri.target); 556 } 557 }; 558 559 class RoseInstrCheckByte 560 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_BYTE, 561 ROSE_STRUCT_CHECK_BYTE, 562 RoseInstrCheckByte> { 563 public: 564 u8 and_mask; 565 u8 cmp_mask; 566 u8 negation; 567 s32 offset; 568 const RoseInstruction *target; 569 RoseInstrCheckByte(u8 and_mask_in,u8 cmp_mask_in,u8 negation_in,s32 offset_in,const RoseInstruction * target_in)570 RoseInstrCheckByte(u8 and_mask_in, u8 cmp_mask_in, u8 negation_in, 571 s32 offset_in, const RoseInstruction *target_in) 572 : and_mask(and_mask_in), cmp_mask(cmp_mask_in), negation(negation_in), 573 offset(offset_in), target(target_in) {} 574 575 bool operator==(const RoseInstrCheckByte &ri) const { 576 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 577 negation == ri.negation && offset == ri.offset && 578 target == ri.target; 579 } 580 hash()581 size_t hash() const override { 582 return hash_all(opcode, and_mask, cmp_mask, negation, offset); 583 } 584 585 void write(void *dest, RoseEngineBlob &blob, 586 const OffsetMap &offset_map) const override; 587 equiv_to(const RoseInstrCheckByte & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)588 bool equiv_to(const RoseInstrCheckByte &ri, const OffsetMap &offsets, 589 const OffsetMap &other_offsets) const { 590 return and_mask == ri.and_mask && cmp_mask == ri.cmp_mask && 591 negation == ri.negation && offset == ri.offset && 592 offsets.at(target) == other_offsets.at(ri.target); 593 } 594 }; 595 596 class RoseInstrCheckShufti16x8 597 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x8, 598 ROSE_STRUCT_CHECK_SHUFTI_16x8, 599 RoseInstrCheckShufti16x8> { 600 public: 601 std::array<u8, 32> nib_mask; 602 std::array<u8, 16> bucket_select_mask; 603 u32 neg_mask; 604 s32 offset; 605 const RoseInstruction *target; 606 RoseInstrCheckShufti16x8(std::array<u8,32> nib_mask_in,std::array<u8,16> bucket_select_mask_in,u32 neg_mask_in,s32 offset_in,const RoseInstruction * target_in)607 RoseInstrCheckShufti16x8(std::array<u8, 32> nib_mask_in, 608 std::array<u8, 16> bucket_select_mask_in, 609 u32 neg_mask_in, s32 offset_in, 610 const RoseInstruction *target_in) 611 : nib_mask(std::move(nib_mask_in)), 612 bucket_select_mask(std::move(bucket_select_mask_in)), 613 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 614 615 bool operator==(const RoseInstrCheckShufti16x8 &ri) const { 616 return nib_mask == ri.nib_mask && 617 bucket_select_mask == ri.bucket_select_mask && 618 neg_mask == ri.neg_mask && offset == ri.offset && 619 target == ri.target; 620 } 621 hash()622 size_t hash() const override { 623 return hash_all(opcode, nib_mask, bucket_select_mask, neg_mask, offset); 624 } 625 626 void write(void *dest, RoseEngineBlob &blob, 627 const OffsetMap &offset_map) const override; 628 equiv_to(const RoseInstrCheckShufti16x8 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)629 bool equiv_to(const RoseInstrCheckShufti16x8 &ri, const OffsetMap &offsets, 630 const OffsetMap &other_offsets) const { 631 return nib_mask == ri.nib_mask && 632 bucket_select_mask == ri.bucket_select_mask && 633 neg_mask == ri.neg_mask && offset == ri.offset && 634 offsets.at(target) == other_offsets.at(ri.target); 635 } 636 }; 637 638 class RoseInstrCheckShufti32x8 639 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x8, 640 ROSE_STRUCT_CHECK_SHUFTI_32x8, 641 RoseInstrCheckShufti32x8> { 642 public: 643 std::array<u8, 16> hi_mask; 644 std::array<u8, 16> lo_mask; 645 std::array<u8, 32> bucket_select_mask; 646 u32 neg_mask; 647 s32 offset; 648 const RoseInstruction *target; 649 RoseInstrCheckShufti32x8(std::array<u8,16> hi_mask_in,std::array<u8,16> lo_mask_in,std::array<u8,32> bucket_select_mask_in,u32 neg_mask_in,s32 offset_in,const RoseInstruction * target_in)650 RoseInstrCheckShufti32x8(std::array<u8, 16> hi_mask_in, 651 std::array<u8, 16> lo_mask_in, 652 std::array<u8, 32> bucket_select_mask_in, 653 u32 neg_mask_in, s32 offset_in, 654 const RoseInstruction *target_in) 655 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 656 bucket_select_mask(std::move(bucket_select_mask_in)), 657 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 658 659 bool operator==(const RoseInstrCheckShufti32x8 &ri) const { 660 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 661 bucket_select_mask == ri.bucket_select_mask && 662 neg_mask == ri.neg_mask && offset == ri.offset && 663 target == ri.target; 664 } 665 hash()666 size_t hash() const override { 667 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask, 668 offset); 669 } 670 671 void write(void *dest, RoseEngineBlob &blob, 672 const OffsetMap &offset_map) const override; 673 equiv_to(const RoseInstrCheckShufti32x8 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)674 bool equiv_to(const RoseInstrCheckShufti32x8 &ri, const OffsetMap &offsets, 675 const OffsetMap &other_offsets) const { 676 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 677 bucket_select_mask == ri.bucket_select_mask && 678 neg_mask == ri.neg_mask && offset == ri.offset && 679 offsets.at(target) == other_offsets.at(ri.target); 680 } 681 }; 682 683 class RoseInstrCheckShufti16x16 684 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_16x16, 685 ROSE_STRUCT_CHECK_SHUFTI_16x16, 686 RoseInstrCheckShufti16x16> { 687 public: 688 std::array<u8, 32> hi_mask; 689 std::array<u8, 32> lo_mask; 690 std::array<u8, 32> bucket_select_mask; 691 u32 neg_mask; 692 s32 offset; 693 const RoseInstruction *target; 694 RoseInstrCheckShufti16x16(std::array<u8,32> hi_mask_in,std::array<u8,32> lo_mask_in,std::array<u8,32> bucket_select_mask_in,u32 neg_mask_in,s32 offset_in,const RoseInstruction * target_in)695 RoseInstrCheckShufti16x16(std::array<u8, 32> hi_mask_in, 696 std::array<u8, 32> lo_mask_in, 697 std::array<u8, 32> bucket_select_mask_in, 698 u32 neg_mask_in, s32 offset_in, 699 const RoseInstruction *target_in) 700 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 701 bucket_select_mask(std::move(bucket_select_mask_in)), 702 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 703 704 bool operator==(const RoseInstrCheckShufti16x16 &ri) const { 705 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 706 bucket_select_mask == ri.bucket_select_mask && 707 neg_mask == ri.neg_mask && offset == ri.offset && 708 target == ri.target; 709 } 710 hash()711 size_t hash() const override { 712 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask, 713 offset); 714 } 715 716 void write(void *dest, RoseEngineBlob &blob, 717 const OffsetMap &offset_map) const override; 718 equiv_to(const RoseInstrCheckShufti16x16 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)719 bool equiv_to(const RoseInstrCheckShufti16x16 &ri, const OffsetMap &offsets, 720 const OffsetMap &other_offsets) const { 721 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 722 bucket_select_mask == ri.bucket_select_mask && 723 neg_mask == ri.neg_mask && offset == ri.offset && 724 offsets.at(target) == other_offsets.at(ri.target); 725 } 726 }; 727 728 class RoseInstrCheckShufti32x16 729 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_32x16, 730 ROSE_STRUCT_CHECK_SHUFTI_32x16, 731 RoseInstrCheckShufti32x16> { 732 public: 733 std::array<u8, 32> hi_mask; 734 std::array<u8, 32> lo_mask; 735 std::array<u8, 32> bucket_select_mask_hi; 736 std::array<u8, 32> bucket_select_mask_lo; 737 u32 neg_mask; 738 s32 offset; 739 const RoseInstruction *target; 740 RoseInstrCheckShufti32x16(std::array<u8,32> hi_mask_in,std::array<u8,32> lo_mask_in,std::array<u8,32> bucket_select_mask_hi_in,std::array<u8,32> bucket_select_mask_lo_in,u32 neg_mask_in,s32 offset_in,const RoseInstruction * target_in)741 RoseInstrCheckShufti32x16(std::array<u8, 32> hi_mask_in, 742 std::array<u8, 32> lo_mask_in, 743 std::array<u8, 32> bucket_select_mask_hi_in, 744 std::array<u8, 32> bucket_select_mask_lo_in, 745 u32 neg_mask_in, s32 offset_in, 746 const RoseInstruction *target_in) 747 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 748 bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)), 749 bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)), 750 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 751 752 bool operator==(const RoseInstrCheckShufti32x16 &ri) const { 753 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 754 bucket_select_mask_hi == ri.bucket_select_mask_hi && 755 bucket_select_mask_lo == ri.bucket_select_mask_lo && 756 neg_mask == ri.neg_mask && offset == ri.offset && 757 target == ri.target; 758 } 759 hash()760 size_t hash() const override { 761 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi, 762 bucket_select_mask_lo, neg_mask, offset); 763 } 764 765 void write(void *dest, RoseEngineBlob &blob, 766 const OffsetMap &offset_map) const override; 767 equiv_to(const RoseInstrCheckShufti32x16 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)768 bool equiv_to(const RoseInstrCheckShufti32x16 &ri, const OffsetMap &offsets, 769 const OffsetMap &other_offsets) const { 770 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 771 bucket_select_mask_hi == ri.bucket_select_mask_hi && 772 bucket_select_mask_lo == ri.bucket_select_mask_lo && 773 neg_mask == ri.neg_mask && offset == ri.offset && 774 offsets.at(target) == other_offsets.at(ri.target); 775 } 776 }; 777 778 class RoseInstrCheckShufti64x8 779 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_64x8, 780 ROSE_STRUCT_CHECK_SHUFTI_64x8, 781 RoseInstrCheckShufti64x8> { 782 public: 783 std::array<u8, 64> hi_mask; 784 std::array<u8, 64> lo_mask; 785 std::array<u8, 64> bucket_select_mask; 786 u64a neg_mask; 787 s32 offset; 788 const RoseInstruction *target; 789 RoseInstrCheckShufti64x8(std::array<u8,64> hi_mask_in,std::array<u8,64> lo_mask_in,std::array<u8,64> bucket_select_mask_in,u64a neg_mask_in,s32 offset_in,const RoseInstruction * target_in)790 RoseInstrCheckShufti64x8(std::array<u8, 64> hi_mask_in, 791 std::array<u8, 64> lo_mask_in, 792 std::array<u8, 64> bucket_select_mask_in, 793 u64a neg_mask_in, s32 offset_in, 794 const RoseInstruction *target_in) 795 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 796 bucket_select_mask(std::move(bucket_select_mask_in)), 797 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 798 799 bool operator==(const RoseInstrCheckShufti64x8 &ri) const { 800 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 801 bucket_select_mask == ri.bucket_select_mask && 802 neg_mask == ri.neg_mask && offset == ri.offset && 803 target == ri.target; 804 } 805 hash()806 size_t hash() const override { 807 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, neg_mask, 808 offset); 809 } 810 811 void write(void *dest, RoseEngineBlob &blob, 812 const OffsetMap &offset_map) const override; 813 equiv_to(const RoseInstrCheckShufti64x8 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)814 bool equiv_to(const RoseInstrCheckShufti64x8 &ri, const OffsetMap &offsets, 815 const OffsetMap &other_offsets) const { 816 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 817 bucket_select_mask == ri.bucket_select_mask && 818 neg_mask == ri.neg_mask && offset == ri.offset && 819 offsets.at(target) == other_offsets.at(ri.target); 820 } 821 }; 822 823 class RoseInstrCheckShufti64x16 824 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_SHUFTI_64x16, 825 ROSE_STRUCT_CHECK_SHUFTI_64x16, 826 RoseInstrCheckShufti64x16> { 827 public: 828 std::array<u8, 64> hi_mask_1; 829 std::array<u8, 64> hi_mask_2; 830 std::array<u8, 64> lo_mask_1; 831 std::array<u8, 64> lo_mask_2; 832 std::array<u8, 64> bucket_select_mask_hi; 833 std::array<u8, 64> bucket_select_mask_lo; 834 u64a neg_mask; 835 s32 offset; 836 const RoseInstruction *target; 837 RoseInstrCheckShufti64x16(std::array<u8,64> hi_mask_1_in,std::array<u8,64> hi_mask_2_in,std::array<u8,64> lo_mask_1_in,std::array<u8,64> lo_mask_2_in,std::array<u8,64> bucket_select_mask_hi_in,std::array<u8,64> bucket_select_mask_lo_in,u64a neg_mask_in,s32 offset_in,const RoseInstruction * target_in)838 RoseInstrCheckShufti64x16(std::array<u8, 64> hi_mask_1_in, 839 std::array<u8, 64> hi_mask_2_in, 840 std::array<u8, 64> lo_mask_1_in, 841 std::array<u8, 64> lo_mask_2_in, 842 std::array<u8, 64> bucket_select_mask_hi_in, 843 std::array<u8, 64> bucket_select_mask_lo_in, 844 u64a neg_mask_in, s32 offset_in, 845 const RoseInstruction *target_in) 846 : hi_mask_1(std::move(hi_mask_1_in)), hi_mask_2(std::move(hi_mask_2_in)), 847 lo_mask_1(std::move(lo_mask_1_in)), lo_mask_2(std::move(lo_mask_2_in)), 848 bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)), 849 bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)), 850 neg_mask(neg_mask_in), offset(offset_in), target(target_in) {} 851 852 bool operator==(const RoseInstrCheckShufti64x16 &ri) const { 853 return hi_mask_1 == ri.hi_mask_1 && hi_mask_2 == ri.hi_mask_2 && 854 lo_mask_1 == ri.lo_mask_1 && lo_mask_2 == ri.lo_mask_2 && 855 bucket_select_mask_hi == ri.bucket_select_mask_hi && 856 bucket_select_mask_lo == ri.bucket_select_mask_lo && 857 neg_mask == ri.neg_mask && offset == ri.offset && 858 target == ri.target; 859 } 860 hash()861 size_t hash() const override { 862 return hash_all(opcode, hi_mask_1, hi_mask_2, lo_mask_1, lo_mask_2, 863 bucket_select_mask_hi, bucket_select_mask_lo, neg_mask, 864 offset); 865 } 866 867 void write(void *dest, RoseEngineBlob &blob, 868 const OffsetMap &offset_map) const override; 869 equiv_to(const RoseInstrCheckShufti64x16 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)870 bool equiv_to(const RoseInstrCheckShufti64x16 &ri, const OffsetMap &offsets, 871 const OffsetMap &other_offsets) const { 872 return hi_mask_1 == ri.hi_mask_1 && hi_mask_2 == ri.hi_mask_2 && 873 lo_mask_1 == ri.lo_mask_1 && lo_mask_2 == ri.lo_mask_2 && 874 bucket_select_mask_hi == ri.bucket_select_mask_hi && 875 bucket_select_mask_lo == ri.bucket_select_mask_lo && 876 neg_mask == ri.neg_mask && offset == ri.offset && 877 offsets.at(target) == other_offsets.at(ri.target); 878 } 879 }; 880 881 class RoseInstrCheckInfix 882 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_INFIX, 883 ROSE_STRUCT_CHECK_INFIX, 884 RoseInstrCheckInfix> { 885 public: 886 u32 queue; 887 u32 lag; 888 ReportID report; 889 const RoseInstruction *target; 890 RoseInstrCheckInfix(u32 queue_in,u32 lag_in,ReportID report_in,const RoseInstruction * target_in)891 RoseInstrCheckInfix(u32 queue_in, u32 lag_in, ReportID report_in, 892 const RoseInstruction *target_in) 893 : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {} 894 895 bool operator==(const RoseInstrCheckInfix &ri) const { 896 return queue == ri.queue && lag == ri.lag && report == ri.report && 897 target == ri.target; 898 } 899 hash()900 size_t hash() const override { 901 return hash_all(opcode, queue, lag, report); 902 } 903 904 void write(void *dest, RoseEngineBlob &blob, 905 const OffsetMap &offset_map) const override; 906 equiv_to(const RoseInstrCheckInfix & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)907 bool equiv_to(const RoseInstrCheckInfix &ri, const OffsetMap &offsets, 908 const OffsetMap &other_offsets) const { 909 return queue == ri.queue && lag == ri.lag && report == ri.report && 910 offsets.at(target) == other_offsets.at(ri.target); 911 } 912 }; 913 914 class RoseInstrCheckPrefix 915 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_PREFIX, 916 ROSE_STRUCT_CHECK_PREFIX, 917 RoseInstrCheckPrefix> { 918 public: 919 u32 queue; 920 u32 lag; 921 ReportID report; 922 const RoseInstruction *target; 923 RoseInstrCheckPrefix(u32 queue_in,u32 lag_in,ReportID report_in,const RoseInstruction * target_in)924 RoseInstrCheckPrefix(u32 queue_in, u32 lag_in, ReportID report_in, 925 const RoseInstruction *target_in) 926 : queue(queue_in), lag(lag_in), report(report_in), target(target_in) {} 927 928 bool operator==(const RoseInstrCheckPrefix &ri) const { 929 return queue == ri.queue && lag == ri.lag && report == ri.report && 930 target == ri.target; 931 } 932 hash()933 size_t hash() const override { 934 return hash_all(opcode, queue, lag, report); 935 } 936 937 void write(void *dest, RoseEngineBlob &blob, 938 const OffsetMap &offset_map) const override; 939 equiv_to(const RoseInstrCheckPrefix & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)940 bool equiv_to(const RoseInstrCheckPrefix &ri, const OffsetMap &offsets, 941 const OffsetMap &other_offsets) const { 942 return queue == ri.queue && lag == ri.lag && report == ri.report && 943 offsets.at(target) == other_offsets.at(ri.target); 944 } 945 }; 946 947 class RoseInstrPushDelayed 948 : public RoseInstrBaseNoTargets<ROSE_INSTR_PUSH_DELAYED, 949 ROSE_STRUCT_PUSH_DELAYED, 950 RoseInstrPushDelayed> { 951 public: 952 u8 delay; 953 u32 index; 954 RoseInstrPushDelayed(u8 delay_in,u32 index_in)955 RoseInstrPushDelayed(u8 delay_in, u32 index_in) 956 : delay(delay_in), index(index_in) {} 957 958 bool operator==(const RoseInstrPushDelayed &ri) const { 959 return delay == ri.delay && index == ri.index; 960 } 961 hash()962 size_t hash() const override { 963 return hash_all(opcode, delay, index); 964 } 965 966 void write(void *dest, RoseEngineBlob &blob, 967 const OffsetMap &offset_map) const override; 968 equiv_to(const RoseInstrPushDelayed & ri,const OffsetMap &,const OffsetMap &)969 bool equiv_to(const RoseInstrPushDelayed &ri, const OffsetMap &, 970 const OffsetMap &) const { 971 return delay == ri.delay && index == ri.index; 972 } 973 }; 974 975 class RoseInstrCatchUp 976 : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP, 977 RoseInstrCatchUp> { 978 public: 979 ~RoseInstrCatchUp() override; 980 }; 981 982 class RoseInstrCatchUpMpv 983 : public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP_MPV, 984 ROSE_STRUCT_CATCH_UP_MPV, 985 RoseInstrCatchUpMpv> { 986 public: 987 ~RoseInstrCatchUpMpv() override; 988 }; 989 990 class RoseInstrSomAdjust 991 : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_ADJUST, 992 ROSE_STRUCT_SOM_ADJUST, 993 RoseInstrSomAdjust> { 994 public: 995 u32 distance; 996 RoseInstrSomAdjust(u32 distance_in)997 explicit RoseInstrSomAdjust(u32 distance_in) : distance(distance_in) {} 998 999 bool operator==(const RoseInstrSomAdjust &ri) const { 1000 return distance == ri.distance; 1001 } 1002 hash()1003 size_t hash() const override { 1004 return hash_all(opcode, distance); 1005 } 1006 1007 void write(void *dest, RoseEngineBlob &blob, 1008 const OffsetMap &offset_map) const override; 1009 equiv_to(const RoseInstrSomAdjust & ri,const OffsetMap &,const OffsetMap &)1010 bool equiv_to(const RoseInstrSomAdjust &ri, const OffsetMap &, 1011 const OffsetMap &) const { 1012 return distance == ri.distance; 1013 } 1014 }; 1015 1016 class RoseInstrSomLeftfix 1017 : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_LEFTFIX, 1018 ROSE_STRUCT_SOM_LEFTFIX, 1019 RoseInstrSomLeftfix> { 1020 public: 1021 u32 queue; 1022 u32 lag; 1023 RoseInstrSomLeftfix(u32 queue_in,u32 lag_in)1024 RoseInstrSomLeftfix(u32 queue_in, u32 lag_in) 1025 : queue(queue_in), lag(lag_in) {} 1026 1027 bool operator==(const RoseInstrSomLeftfix &ri) const { 1028 return queue == ri.queue && lag == ri.lag; 1029 } 1030 hash()1031 size_t hash() const override { 1032 return hash_all(opcode, queue, lag); 1033 } 1034 1035 void write(void *dest, RoseEngineBlob &blob, 1036 const OffsetMap &offset_map) const override; 1037 equiv_to(const RoseInstrSomLeftfix & ri,const OffsetMap &,const OffsetMap &)1038 bool equiv_to(const RoseInstrSomLeftfix &ri, const OffsetMap &, 1039 const OffsetMap &) const { 1040 return queue == ri.queue && lag == ri.lag; 1041 } 1042 }; 1043 1044 class RoseInstrSomFromReport 1045 : public RoseInstrBaseNoTargets<ROSE_INSTR_SOM_FROM_REPORT, 1046 ROSE_STRUCT_SOM_FROM_REPORT, 1047 RoseInstrSomFromReport> { 1048 public: 1049 som_operation som; 1050 RoseInstrSomFromReport()1051 RoseInstrSomFromReport() { 1052 std::memset(&som, 0, sizeof(som)); 1053 } 1054 1055 bool operator==(const RoseInstrSomFromReport &ri) const { 1056 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1057 } 1058 hash()1059 size_t hash() const override { 1060 return hash_all(opcode, som.type, som.onmatch); 1061 } 1062 1063 void write(void *dest, RoseEngineBlob &blob, 1064 const OffsetMap &offset_map) const override; 1065 equiv_to(const RoseInstrSomFromReport & ri,const OffsetMap &,const OffsetMap &)1066 bool equiv_to(const RoseInstrSomFromReport &ri, const OffsetMap &, 1067 const OffsetMap &) const { 1068 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1069 } 1070 }; 1071 1072 class RoseInstrSomZero 1073 : public RoseInstrBaseTrivial<ROSE_INSTR_SOM_ZERO, ROSE_STRUCT_SOM_ZERO, 1074 RoseInstrSomZero> { 1075 public: 1076 ~RoseInstrSomZero() override; 1077 }; 1078 1079 class RoseInstrTriggerInfix 1080 : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_INFIX, 1081 ROSE_STRUCT_TRIGGER_INFIX, 1082 RoseInstrTriggerInfix> { 1083 public: 1084 u8 cancel; 1085 u32 queue; 1086 u32 event; 1087 RoseInstrTriggerInfix(u8 cancel_in,u32 queue_in,u32 event_in)1088 RoseInstrTriggerInfix(u8 cancel_in, u32 queue_in, u32 event_in) 1089 : cancel(cancel_in), queue(queue_in), event(event_in) {} 1090 1091 bool operator==(const RoseInstrTriggerInfix &ri) const { 1092 return cancel == ri.cancel && queue == ri.queue && event == ri.event; 1093 } 1094 hash()1095 size_t hash() const override { 1096 return hash_all(opcode, cancel, queue, event); 1097 } 1098 1099 void write(void *dest, RoseEngineBlob &blob, 1100 const OffsetMap &offset_map) const override; 1101 equiv_to(const RoseInstrTriggerInfix & ri,const OffsetMap &,const OffsetMap &)1102 bool equiv_to(const RoseInstrTriggerInfix &ri, const OffsetMap &, 1103 const OffsetMap &) const { 1104 return cancel == ri.cancel && queue == ri.queue && event == ri.event; 1105 } 1106 }; 1107 1108 class RoseInstrTriggerSuffix 1109 : public RoseInstrBaseNoTargets<ROSE_INSTR_TRIGGER_SUFFIX, 1110 ROSE_STRUCT_TRIGGER_SUFFIX, 1111 RoseInstrTriggerSuffix> { 1112 public: 1113 u32 queue; 1114 u32 event; 1115 RoseInstrTriggerSuffix(u32 queue_in,u32 event_in)1116 RoseInstrTriggerSuffix(u32 queue_in, u32 event_in) 1117 : queue(queue_in), event(event_in) {} 1118 1119 bool operator==(const RoseInstrTriggerSuffix &ri) const { 1120 return queue == ri.queue && event == ri.event; 1121 } 1122 hash()1123 size_t hash() const override { 1124 return hash_all(opcode, queue, event); 1125 } 1126 1127 void write(void *dest, RoseEngineBlob &blob, 1128 const OffsetMap &offset_map) const override; 1129 equiv_to(const RoseInstrTriggerSuffix & ri,const OffsetMap &,const OffsetMap &)1130 bool equiv_to(const RoseInstrTriggerSuffix &ri, const OffsetMap &, 1131 const OffsetMap &) const { 1132 return queue == ri.queue && event == ri.event; 1133 } 1134 }; 1135 1136 class RoseInstrDedupe 1137 : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE, ROSE_STRUCT_DEDUPE, 1138 RoseInstrDedupe> { 1139 public: 1140 u8 quash_som; 1141 u32 dkey; 1142 s32 offset_adjust; 1143 const RoseInstruction *target; 1144 RoseInstrDedupe(u8 quash_som_in,u32 dkey_in,s32 offset_adjust_in,const RoseInstruction * target_in)1145 RoseInstrDedupe(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in, 1146 const RoseInstruction *target_in) 1147 : quash_som(quash_som_in), dkey(dkey_in), 1148 offset_adjust(offset_adjust_in), target(target_in) {} 1149 1150 bool operator==(const RoseInstrDedupe &ri) const { 1151 return quash_som == ri.quash_som && dkey == ri.dkey && 1152 offset_adjust == ri.offset_adjust && target == ri.target; 1153 } 1154 hash()1155 size_t hash() const override { 1156 return hash_all(opcode, quash_som, dkey, offset_adjust); 1157 } 1158 1159 void write(void *dest, RoseEngineBlob &blob, 1160 const OffsetMap &offset_map) const override; 1161 equiv_to(const RoseInstrDedupe & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1162 bool equiv_to(const RoseInstrDedupe &ri, const OffsetMap &offsets, 1163 const OffsetMap &other_offsets) const { 1164 return quash_som == ri.quash_som && dkey == ri.dkey && 1165 offset_adjust == ri.offset_adjust && 1166 offsets.at(target) == other_offsets.at(ri.target); 1167 } 1168 }; 1169 1170 class RoseInstrDedupeSom 1171 : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_SOM, 1172 ROSE_STRUCT_DEDUPE_SOM, 1173 RoseInstrDedupeSom> { 1174 public: 1175 u8 quash_som; 1176 u32 dkey; 1177 s32 offset_adjust; 1178 const RoseInstruction *target; 1179 RoseInstrDedupeSom(u8 quash_som_in,u32 dkey_in,s32 offset_adjust_in,const RoseInstruction * target_in)1180 RoseInstrDedupeSom(u8 quash_som_in, u32 dkey_in, s32 offset_adjust_in, 1181 const RoseInstruction *target_in) 1182 : quash_som(quash_som_in), dkey(dkey_in), 1183 offset_adjust(offset_adjust_in), target(target_in) {} 1184 1185 bool operator==(const RoseInstrDedupeSom &ri) const { 1186 return quash_som == ri.quash_som && dkey == ri.dkey && 1187 offset_adjust == ri.offset_adjust && target == ri.target; 1188 } 1189 hash()1190 size_t hash() const override { 1191 return hash_all(opcode, quash_som, dkey, offset_adjust); 1192 } 1193 1194 void write(void *dest, RoseEngineBlob &blob, 1195 const OffsetMap &offset_map) const override; 1196 equiv_to(const RoseInstrDedupeSom & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1197 bool equiv_to(const RoseInstrDedupeSom &ri, const OffsetMap &offsets, 1198 const OffsetMap &other_offsets) const { 1199 return quash_som == ri.quash_som && dkey == ri.dkey && 1200 offset_adjust == ri.offset_adjust && 1201 offsets.at(target) == other_offsets.at(ri.target); 1202 } 1203 }; 1204 1205 class RoseInstrReportChain 1206 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_CHAIN, 1207 ROSE_STRUCT_REPORT_CHAIN, 1208 RoseInstrReportChain> { 1209 public: 1210 u32 event; 1211 u64a top_squash_distance; 1212 RoseInstrReportChain(u32 event_in,u32 top_squash_distance_in)1213 RoseInstrReportChain(u32 event_in, u32 top_squash_distance_in) 1214 : event(event_in), top_squash_distance(top_squash_distance_in) {} 1215 1216 bool operator==(const RoseInstrReportChain &ri) const { 1217 return event == ri.event && 1218 top_squash_distance == ri.top_squash_distance; 1219 } 1220 hash()1221 size_t hash() const override { 1222 return hash_all(opcode, event, top_squash_distance); 1223 } 1224 1225 void write(void *dest, RoseEngineBlob &blob, 1226 const OffsetMap &offset_map) const override; 1227 equiv_to(const RoseInstrReportChain & ri,const OffsetMap &,const OffsetMap &)1228 bool equiv_to(const RoseInstrReportChain &ri, const OffsetMap &, 1229 const OffsetMap &) const { 1230 return event == ri.event && 1231 top_squash_distance == ri.top_squash_distance; 1232 } 1233 }; 1234 1235 class RoseInstrReportSomInt 1236 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_INT, 1237 ROSE_STRUCT_REPORT_SOM_INT, 1238 RoseInstrReportSomInt> { 1239 public: 1240 som_operation som; 1241 RoseInstrReportSomInt()1242 RoseInstrReportSomInt() { 1243 std::memset(&som, 0, sizeof(som)); 1244 } 1245 1246 bool operator==(const RoseInstrReportSomInt &ri) const { 1247 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1248 } 1249 hash()1250 size_t hash() const override { 1251 return hash_all(opcode, som.type, som.onmatch); 1252 } 1253 1254 void write(void *dest, RoseEngineBlob &blob, 1255 const OffsetMap &offset_map) const override; 1256 equiv_to(const RoseInstrReportSomInt & ri,const OffsetMap &,const OffsetMap &)1257 bool equiv_to(const RoseInstrReportSomInt &ri, const OffsetMap &, 1258 const OffsetMap &) const { 1259 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1260 } 1261 }; 1262 1263 class RoseInstrReportSomAware 1264 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_AWARE, 1265 ROSE_STRUCT_REPORT_SOM_AWARE, 1266 RoseInstrReportSomAware> { 1267 public: 1268 som_operation som; 1269 RoseInstrReportSomAware()1270 RoseInstrReportSomAware() { 1271 std::memset(&som, 0, sizeof(som)); 1272 } 1273 1274 bool operator==(const RoseInstrReportSomAware &ri) const { 1275 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1276 } 1277 hash()1278 size_t hash() const override { 1279 return hash_all(opcode, som.type, som.onmatch); 1280 } 1281 1282 void write(void *dest, RoseEngineBlob &blob, 1283 const OffsetMap &offset_map) const override; 1284 equiv_to(const RoseInstrReportSomAware & ri,const OffsetMap &,const OffsetMap &)1285 bool equiv_to(const RoseInstrReportSomAware &ri, const OffsetMap &, 1286 const OffsetMap &) const { 1287 return std::memcmp(&som, &ri.som, sizeof(som)) == 0; 1288 } 1289 }; 1290 1291 class RoseInstrReport 1292 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT, ROSE_STRUCT_REPORT, 1293 RoseInstrReport> { 1294 public: 1295 ReportID onmatch; 1296 s32 offset_adjust; 1297 RoseInstrReport(ReportID onmatch_in,s32 offset_adjust_in)1298 RoseInstrReport(ReportID onmatch_in, s32 offset_adjust_in) 1299 : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {} 1300 1301 bool operator==(const RoseInstrReport &ri) const { 1302 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1303 } 1304 hash()1305 size_t hash() const override { 1306 return hash_all(opcode, onmatch, offset_adjust); 1307 } 1308 1309 void write(void *dest, RoseEngineBlob &blob, 1310 const OffsetMap &offset_map) const override; 1311 equiv_to(const RoseInstrReport & ri,const OffsetMap &,const OffsetMap &)1312 bool equiv_to(const RoseInstrReport &ri, const OffsetMap &, 1313 const OffsetMap &) const { 1314 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1315 } 1316 }; 1317 1318 class RoseInstrReportExhaust 1319 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_EXHAUST, 1320 ROSE_STRUCT_REPORT_EXHAUST, 1321 RoseInstrReportExhaust> { 1322 public: 1323 ReportID onmatch; 1324 s32 offset_adjust; 1325 u32 ekey; 1326 RoseInstrReportExhaust(ReportID onmatch_in,s32 offset_adjust_in,u32 ekey_in)1327 RoseInstrReportExhaust(ReportID onmatch_in, s32 offset_adjust_in, 1328 u32 ekey_in) 1329 : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {} 1330 1331 bool operator==(const RoseInstrReportExhaust &ri) const { 1332 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1333 ekey == ri.ekey; 1334 } 1335 hash()1336 size_t hash() const override { 1337 return hash_all(opcode, onmatch, offset_adjust, ekey); 1338 } 1339 1340 void write(void *dest, RoseEngineBlob &blob, 1341 const OffsetMap &offset_map) const override; 1342 equiv_to(const RoseInstrReportExhaust & ri,const OffsetMap &,const OffsetMap &)1343 bool equiv_to(const RoseInstrReportExhaust &ri, const OffsetMap &, 1344 const OffsetMap &) const { 1345 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1346 ekey == ri.ekey; 1347 } 1348 }; 1349 1350 class RoseInstrReportSom 1351 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM, 1352 ROSE_STRUCT_REPORT_SOM, 1353 RoseInstrReportSom> { 1354 public: 1355 ReportID onmatch; 1356 s32 offset_adjust; 1357 RoseInstrReportSom(ReportID onmatch_in,s32 offset_adjust_in)1358 RoseInstrReportSom(ReportID onmatch_in, s32 offset_adjust_in) 1359 : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {} 1360 1361 bool operator==(const RoseInstrReportSom &ri) const { 1362 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1363 } 1364 hash()1365 size_t hash() const override { 1366 return hash_all(opcode, onmatch, offset_adjust); 1367 } 1368 1369 void write(void *dest, RoseEngineBlob &blob, 1370 const OffsetMap &offset_map) const override; 1371 equiv_to(const RoseInstrReportSom & ri,const OffsetMap &,const OffsetMap &)1372 bool equiv_to(const RoseInstrReportSom &ri, const OffsetMap &, 1373 const OffsetMap &) const { 1374 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1375 } 1376 }; 1377 1378 class RoseInstrReportSomExhaust 1379 : public RoseInstrBaseNoTargets<ROSE_INSTR_REPORT_SOM_EXHAUST, 1380 ROSE_STRUCT_REPORT_SOM_EXHAUST, 1381 RoseInstrReportSomExhaust> { 1382 public: 1383 ReportID onmatch; 1384 s32 offset_adjust; 1385 u32 ekey; 1386 RoseInstrReportSomExhaust(ReportID onmatch_in,s32 offset_adjust_in,u32 ekey_in)1387 RoseInstrReportSomExhaust(ReportID onmatch_in, s32 offset_adjust_in, 1388 u32 ekey_in) 1389 : onmatch(onmatch_in), offset_adjust(offset_adjust_in), ekey(ekey_in) {} 1390 1391 bool operator==(const RoseInstrReportSomExhaust &ri) const { 1392 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1393 ekey == ri.ekey; 1394 } 1395 hash()1396 size_t hash() const override { 1397 return hash_all(opcode, onmatch, offset_adjust, ekey); 1398 } 1399 1400 void write(void *dest, RoseEngineBlob &blob, 1401 const OffsetMap &offset_map) const override; 1402 equiv_to(const RoseInstrReportSomExhaust & ri,const OffsetMap &,const OffsetMap &)1403 bool equiv_to(const RoseInstrReportSomExhaust &ri, const OffsetMap &, 1404 const OffsetMap &) const { 1405 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1406 ekey == ri.ekey; 1407 } 1408 }; 1409 1410 class RoseInstrDedupeAndReport 1411 : public RoseInstrBaseOneTarget<ROSE_INSTR_DEDUPE_AND_REPORT, 1412 ROSE_STRUCT_DEDUPE_AND_REPORT, 1413 RoseInstrDedupeAndReport> { 1414 public: 1415 u8 quash_som; 1416 u32 dkey; 1417 ReportID onmatch; 1418 s32 offset_adjust; 1419 const RoseInstruction *target; 1420 RoseInstrDedupeAndReport(u8 quash_som_in,u32 dkey_in,ReportID onmatch_in,s32 offset_adjust_in,const RoseInstruction * target_in)1421 RoseInstrDedupeAndReport(u8 quash_som_in, u32 dkey_in, ReportID onmatch_in, 1422 s32 offset_adjust_in, 1423 const RoseInstruction *target_in) 1424 : quash_som(quash_som_in), dkey(dkey_in), onmatch(onmatch_in), 1425 offset_adjust(offset_adjust_in), target(target_in) {} 1426 1427 bool operator==(const RoseInstrDedupeAndReport &ri) const { 1428 return quash_som == ri.quash_som && dkey == ri.dkey && 1429 onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1430 target == ri.target; 1431 } 1432 hash()1433 size_t hash() const override { 1434 return hash_all(opcode, quash_som, dkey, onmatch, offset_adjust); 1435 } 1436 1437 void write(void *dest, RoseEngineBlob &blob, 1438 const OffsetMap &offset_map) const override; 1439 equiv_to(const RoseInstrDedupeAndReport & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1440 bool equiv_to(const RoseInstrDedupeAndReport &ri, const OffsetMap &offsets, 1441 const OffsetMap &other_offsets) const { 1442 return quash_som == ri.quash_som && dkey == ri.dkey && 1443 onmatch == ri.onmatch && offset_adjust == ri.offset_adjust && 1444 offsets.at(target) == other_offsets.at(ri.target); 1445 } 1446 }; 1447 1448 class RoseInstrFinalReport 1449 : public RoseInstrBaseNoTargets<ROSE_INSTR_FINAL_REPORT, 1450 ROSE_STRUCT_FINAL_REPORT, 1451 RoseInstrFinalReport> { 1452 public: 1453 ReportID onmatch; 1454 s32 offset_adjust; 1455 RoseInstrFinalReport(ReportID onmatch_in,s32 offset_adjust_in)1456 RoseInstrFinalReport(ReportID onmatch_in, s32 offset_adjust_in) 1457 : onmatch(onmatch_in), offset_adjust(offset_adjust_in) {} 1458 1459 bool operator==(const RoseInstrFinalReport &ri) const { 1460 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1461 } 1462 hash()1463 size_t hash() const override { 1464 return hash_all(opcode, onmatch, offset_adjust); 1465 } 1466 1467 void write(void *dest, RoseEngineBlob &blob, 1468 const OffsetMap &offset_map) const override; 1469 equiv_to(const RoseInstrFinalReport & ri,const OffsetMap &,const OffsetMap &)1470 bool equiv_to(const RoseInstrFinalReport &ri, const OffsetMap &, 1471 const OffsetMap &) const { 1472 return onmatch == ri.onmatch && offset_adjust == ri.offset_adjust; 1473 } 1474 }; 1475 1476 class RoseInstrCheckExhausted 1477 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_EXHAUSTED, 1478 ROSE_STRUCT_CHECK_EXHAUSTED, 1479 RoseInstrCheckExhausted> { 1480 public: 1481 u32 ekey; 1482 const RoseInstruction *target; 1483 RoseInstrCheckExhausted(u32 ekey_in,const RoseInstruction * target_in)1484 RoseInstrCheckExhausted(u32 ekey_in, const RoseInstruction *target_in) 1485 : ekey(ekey_in), target(target_in) {} 1486 1487 bool operator==(const RoseInstrCheckExhausted &ri) const { 1488 return ekey == ri.ekey && target == ri.target; 1489 } 1490 hash()1491 size_t hash() const override { 1492 return hash_all(opcode, ekey); 1493 } 1494 1495 void write(void *dest, RoseEngineBlob &blob, 1496 const OffsetMap &offset_map) const override; 1497 equiv_to(const RoseInstrCheckExhausted & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1498 bool equiv_to(const RoseInstrCheckExhausted &ri, const OffsetMap &offsets, 1499 const OffsetMap &other_offsets) const { 1500 return ekey == ri.ekey && 1501 offsets.at(target) == other_offsets.at(ri.target); 1502 } 1503 }; 1504 1505 class RoseInstrCheckMinLength 1506 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MIN_LENGTH, 1507 ROSE_STRUCT_CHECK_MIN_LENGTH, 1508 RoseInstrCheckMinLength> { 1509 public: 1510 s32 end_adj; 1511 u64a min_length; 1512 const RoseInstruction *target; 1513 RoseInstrCheckMinLength(s32 end_adj_in,u64a min_length_in,const RoseInstruction * target_in)1514 RoseInstrCheckMinLength(s32 end_adj_in, u64a min_length_in, 1515 const RoseInstruction *target_in) 1516 : end_adj(end_adj_in), min_length(min_length_in), target(target_in) {} 1517 1518 bool operator==(const RoseInstrCheckMinLength &ri) const { 1519 return end_adj == ri.end_adj && min_length == ri.min_length && 1520 target == ri.target; 1521 } 1522 hash()1523 size_t hash() const override { 1524 return hash_all(opcode, end_adj, min_length); 1525 } 1526 1527 void write(void *dest, RoseEngineBlob &blob, 1528 const OffsetMap &offset_map) const override; 1529 equiv_to(const RoseInstrCheckMinLength & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1530 bool equiv_to(const RoseInstrCheckMinLength &ri, const OffsetMap &offsets, 1531 const OffsetMap &other_offsets) const { 1532 return end_adj == ri.end_adj && min_length == ri.min_length && 1533 offsets.at(target) == other_offsets.at(ri.target); 1534 } 1535 }; 1536 1537 class RoseInstrSetState 1538 : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_STATE, ROSE_STRUCT_SET_STATE, 1539 RoseInstrSetState> { 1540 public: 1541 u32 index; 1542 RoseInstrSetState(u32 index_in)1543 explicit RoseInstrSetState(u32 index_in) : index(index_in) {} 1544 1545 bool operator==(const RoseInstrSetState &ri) const { 1546 return index == ri.index; 1547 } 1548 hash()1549 size_t hash() const override { 1550 return hash_all(opcode, index); 1551 } 1552 1553 void write(void *dest, RoseEngineBlob &blob, 1554 const OffsetMap &offset_map) const override; 1555 equiv_to(const RoseInstrSetState & ri,const OffsetMap &,const OffsetMap &)1556 bool equiv_to(const RoseInstrSetState &ri, const OffsetMap &, 1557 const OffsetMap &) const { 1558 return index == ri.index; 1559 } 1560 }; 1561 1562 class RoseInstrSetGroups 1563 : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_GROUPS, 1564 ROSE_STRUCT_SET_GROUPS, 1565 RoseInstrSetGroups> { 1566 public: 1567 rose_group groups; 1568 RoseInstrSetGroups(rose_group groups_in)1569 explicit RoseInstrSetGroups(rose_group groups_in) : groups(groups_in) {} 1570 1571 bool operator==(const RoseInstrSetGroups &ri) const { 1572 return groups == ri.groups; 1573 } 1574 hash()1575 size_t hash() const override { 1576 return hash_all(opcode, groups); 1577 } 1578 1579 void write(void *dest, RoseEngineBlob &blob, 1580 const OffsetMap &offset_map) const override; 1581 equiv_to(const RoseInstrSetGroups & ri,const OffsetMap &,const OffsetMap &)1582 bool equiv_to(const RoseInstrSetGroups &ri, const OffsetMap &, 1583 const OffsetMap &) const { 1584 return groups == ri.groups; 1585 } 1586 }; 1587 1588 class RoseInstrSquashGroups 1589 : public RoseInstrBaseNoTargets<ROSE_INSTR_SQUASH_GROUPS, 1590 ROSE_STRUCT_SQUASH_GROUPS, 1591 RoseInstrSquashGroups> { 1592 public: 1593 rose_group groups; 1594 RoseInstrSquashGroups(rose_group groups_in)1595 explicit RoseInstrSquashGroups(rose_group groups_in) : groups(groups_in) {} 1596 1597 bool operator==(const RoseInstrSquashGroups &ri) const { 1598 return groups == ri.groups; 1599 } 1600 hash()1601 size_t hash() const override { 1602 return hash_all(opcode, groups); 1603 } 1604 1605 void write(void *dest, RoseEngineBlob &blob, 1606 const OffsetMap &offset_map) const override; 1607 equiv_to(const RoseInstrSquashGroups & ri,const OffsetMap &,const OffsetMap &)1608 bool equiv_to(const RoseInstrSquashGroups &ri, const OffsetMap &, 1609 const OffsetMap &) const { 1610 return groups == ri.groups; 1611 } 1612 }; 1613 1614 class RoseInstrCheckState 1615 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_STATE, 1616 ROSE_STRUCT_CHECK_STATE, 1617 RoseInstrCheckState> { 1618 public: 1619 u32 index; 1620 const RoseInstruction *target; 1621 RoseInstrCheckState(u32 index_in,const RoseInstruction * target_in)1622 RoseInstrCheckState(u32 index_in, const RoseInstruction *target_in) 1623 : index(index_in), target(target_in) {} 1624 1625 bool operator==(const RoseInstrCheckState &ri) const { 1626 return index == ri.index && target == ri.target; 1627 } 1628 hash()1629 size_t hash() const override { 1630 return hash_all(opcode, index); 1631 } 1632 1633 void write(void *dest, RoseEngineBlob &blob, 1634 const OffsetMap &offset_map) const override; 1635 equiv_to(const RoseInstrCheckState & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1636 bool equiv_to(const RoseInstrCheckState &ri, const OffsetMap &offsets, 1637 const OffsetMap &other_offsets) const { 1638 return index == ri.index && 1639 offsets.at(target) == other_offsets.at(ri.target); 1640 } 1641 }; 1642 1643 class RoseInstrSparseIterBegin 1644 : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_BEGIN, 1645 ROSE_STRUCT_SPARSE_ITER_BEGIN, 1646 RoseInstrSparseIterBegin> { 1647 public: 1648 u32 num_keys; // total number of multibit keys 1649 std::vector<std::pair<u32, const RoseInstruction *>> jump_table; 1650 const RoseInstruction *target; 1651 RoseInstrSparseIterBegin(u32 num_keys_in,const RoseInstruction * target_in)1652 RoseInstrSparseIterBegin(u32 num_keys_in, 1653 const RoseInstruction *target_in) 1654 : num_keys(num_keys_in), target(target_in) {} 1655 1656 bool operator==(const RoseInstrSparseIterBegin &ri) const { 1657 return num_keys == ri.num_keys && jump_table == ri.jump_table && 1658 target == ri.target; 1659 } 1660 hash()1661 size_t hash() const override { 1662 size_t v = hash_all(opcode, num_keys); 1663 for (const u32 &key : jump_table | boost::adaptors::map_keys) { 1664 hash_combine(v, key); 1665 } 1666 return v; 1667 } 1668 1669 void write(void *dest, RoseEngineBlob &blob, 1670 const OffsetMap &offset_map) const override; 1671 update_target(const RoseInstruction * old_target,const RoseInstruction * new_target)1672 void update_target(const RoseInstruction *old_target, 1673 const RoseInstruction *new_target) override { 1674 if (target == old_target) { 1675 target = new_target; 1676 } 1677 for (auto &jump : jump_table) { 1678 if (jump.second == old_target) { 1679 jump.second = new_target; 1680 } 1681 } 1682 } 1683 equiv_to(const RoseInstrSparseIterBegin & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1684 bool equiv_to(const RoseInstrSparseIterBegin &ri, const OffsetMap &offsets, 1685 const OffsetMap &other_offsets) const { 1686 if (iter_offset != ri.iter_offset || 1687 offsets.at(target) != other_offsets.at(ri.target)) { 1688 return false; 1689 } 1690 if (jump_table.size() != ri.jump_table.size()) { 1691 return false; 1692 } 1693 auto it1 = jump_table.begin(), it2 = ri.jump_table.begin(); 1694 for (; it1 != jump_table.end(); ++it1, ++it2) { 1695 if (it1->first != it2->first) { 1696 return false; 1697 } 1698 if (offsets.at(it1->second) != other_offsets.at(it2->second)) { 1699 return false; 1700 } 1701 } 1702 return true; 1703 } 1704 1705 private: 1706 friend class RoseInstrSparseIterNext; 1707 1708 // These variables allow us to use the same multibit iterator and jump 1709 // table in subsequent SPARSE_ITER_NEXT write() operations. 1710 mutable bool is_written = false; 1711 mutable u32 iter_offset = 0; 1712 mutable u32 jump_table_offset = 0; 1713 }; 1714 1715 class RoseInstrSparseIterNext 1716 : public RoseInstrBase<ROSE_INSTR_SPARSE_ITER_NEXT, 1717 ROSE_STRUCT_SPARSE_ITER_NEXT, 1718 RoseInstrSparseIterNext> { 1719 public: 1720 u32 state; 1721 const RoseInstrSparseIterBegin *begin; 1722 const RoseInstruction *target; 1723 RoseInstrSparseIterNext(u32 state_in,const RoseInstrSparseIterBegin * begin_in,const RoseInstruction * target_in)1724 RoseInstrSparseIterNext(u32 state_in, 1725 const RoseInstrSparseIterBegin *begin_in, 1726 const RoseInstruction *target_in) 1727 : state(state_in), begin(begin_in), target(target_in) {} 1728 1729 bool operator==(const RoseInstrSparseIterNext &ri) const { 1730 return state == ri.state && begin == ri.begin && target == ri.target; 1731 } 1732 hash()1733 size_t hash() const override { 1734 return hash_all(opcode, state); 1735 } 1736 1737 void write(void *dest, RoseEngineBlob &blob, 1738 const OffsetMap &offset_map) const override; 1739 update_target(const RoseInstruction * old_target,const RoseInstruction * new_target)1740 void update_target(const RoseInstruction *old_target, 1741 const RoseInstruction *new_target) override { 1742 if (target == old_target) { 1743 target = new_target; 1744 } 1745 if (begin == old_target) { 1746 assert(new_target->code() == ROSE_INSTR_SPARSE_ITER_BEGIN); 1747 begin = static_cast<const RoseInstrSparseIterBegin *>(new_target); 1748 } 1749 } 1750 equiv_to(const RoseInstrSparseIterNext & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1751 bool equiv_to(const RoseInstrSparseIterNext &ri, const OffsetMap &offsets, 1752 const OffsetMap &other_offsets) const { 1753 return state == ri.state && 1754 offsets.at(begin) == other_offsets.at(ri.begin) && 1755 offsets.at(target) == other_offsets.at(ri.target); 1756 } 1757 }; 1758 1759 class RoseInstrSparseIterAny 1760 : public RoseInstrBaseOneTarget<ROSE_INSTR_SPARSE_ITER_ANY, 1761 ROSE_STRUCT_SPARSE_ITER_ANY, 1762 RoseInstrSparseIterAny> { 1763 public: 1764 u32 num_keys; // total number of multibit keys 1765 std::vector<u32> keys; 1766 const RoseInstruction *target; 1767 RoseInstrSparseIterAny(u32 num_keys_in,std::vector<u32> keys_in,const RoseInstruction * target_in)1768 RoseInstrSparseIterAny(u32 num_keys_in, std::vector<u32> keys_in, 1769 const RoseInstruction *target_in) 1770 : num_keys(num_keys_in), keys(std::move(keys_in)), target(target_in) {} 1771 1772 bool operator==(const RoseInstrSparseIterAny &ri) const { 1773 return num_keys == ri.num_keys && keys == ri.keys && 1774 target == ri.target; 1775 } 1776 hash()1777 size_t hash() const override { 1778 return hash_all(opcode, num_keys, keys); 1779 } 1780 1781 void write(void *dest, RoseEngineBlob &blob, 1782 const OffsetMap &offset_map) const override; 1783 equiv_to(const RoseInstrSparseIterAny & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1784 bool equiv_to(const RoseInstrSparseIterAny &ri, const OffsetMap &offsets, 1785 const OffsetMap &other_offsets) const { 1786 return num_keys == ri.num_keys && keys == ri.keys && 1787 offsets.at(target) == other_offsets.at(ri.target); 1788 } 1789 }; 1790 1791 class RoseInstrEnginesEod 1792 : public RoseInstrBaseNoTargets<ROSE_INSTR_ENGINES_EOD, 1793 ROSE_STRUCT_ENGINES_EOD, 1794 RoseInstrEnginesEod> { 1795 public: 1796 u32 iter_offset; 1797 RoseInstrEnginesEod(u32 iter_in)1798 explicit RoseInstrEnginesEod(u32 iter_in) : iter_offset(iter_in) {} 1799 1800 bool operator==(const RoseInstrEnginesEod &ri) const { 1801 return iter_offset == ri.iter_offset; 1802 } 1803 hash()1804 size_t hash() const override { 1805 return hash_all(opcode, iter_offset); 1806 } 1807 1808 void write(void *dest, RoseEngineBlob &blob, 1809 const OffsetMap &offset_map) const override; 1810 equiv_to(const RoseInstrEnginesEod & ri,const OffsetMap &,const OffsetMap &)1811 bool equiv_to(const RoseInstrEnginesEod &ri, const OffsetMap &, 1812 const OffsetMap &) const { 1813 return iter_offset == ri.iter_offset; 1814 } 1815 }; 1816 1817 class RoseInstrSuffixesEod 1818 : public RoseInstrBaseTrivial<ROSE_INSTR_SUFFIXES_EOD, 1819 ROSE_STRUCT_SUFFIXES_EOD, 1820 RoseInstrSuffixesEod> { 1821 public: 1822 ~RoseInstrSuffixesEod() override; 1823 }; 1824 1825 class RoseInstrMatcherEod : public RoseInstrBaseTrivial<ROSE_INSTR_MATCHER_EOD, 1826 ROSE_STRUCT_MATCHER_EOD, 1827 RoseInstrMatcherEod> { 1828 public: 1829 ~RoseInstrMatcherEod() override; 1830 }; 1831 1832 class RoseInstrCheckLongLit 1833 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT, 1834 ROSE_STRUCT_CHECK_LONG_LIT, 1835 RoseInstrCheckLongLit> { 1836 public: 1837 std::string literal; 1838 const RoseInstruction *target; 1839 RoseInstrCheckLongLit(std::string literal_in,const RoseInstruction * target_in)1840 RoseInstrCheckLongLit(std::string literal_in, 1841 const RoseInstruction *target_in) 1842 : literal(std::move(literal_in)), target(target_in) {} 1843 1844 bool operator==(const RoseInstrCheckLongLit &ri) const { 1845 return literal == ri.literal && target == ri.target; 1846 } 1847 hash()1848 size_t hash() const override { 1849 return hash_all(opcode, literal); 1850 } 1851 1852 void write(void *dest, RoseEngineBlob &blob, 1853 const OffsetMap &offset_map) const override; 1854 equiv_to(const RoseInstrCheckLongLit & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1855 bool equiv_to(const RoseInstrCheckLongLit &ri, const OffsetMap &offsets, 1856 const OffsetMap &other_offsets) const { 1857 return literal == ri.literal && 1858 offsets.at(target) == other_offsets.at(ri.target); 1859 } 1860 }; 1861 1862 class RoseInstrCheckLongLitNocase 1863 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_LONG_LIT_NOCASE, 1864 ROSE_STRUCT_CHECK_LONG_LIT_NOCASE, 1865 RoseInstrCheckLongLitNocase> { 1866 public: 1867 std::string literal; 1868 const RoseInstruction *target; 1869 RoseInstrCheckLongLitNocase(std::string literal_in,const RoseInstruction * target_in)1870 RoseInstrCheckLongLitNocase(std::string literal_in, 1871 const RoseInstruction *target_in) 1872 : literal(std::move(literal_in)), target(target_in) { 1873 upperString(literal); 1874 } 1875 1876 bool operator==(const RoseInstrCheckLongLitNocase &ri) const { 1877 return literal == ri.literal && target == ri.target; 1878 } 1879 hash()1880 size_t hash() const override { 1881 return hash_all(opcode, literal); 1882 } 1883 1884 void write(void *dest, RoseEngineBlob &blob, 1885 const OffsetMap &offset_map) const override; 1886 equiv_to(const RoseInstrCheckLongLitNocase & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1887 bool equiv_to(const RoseInstrCheckLongLitNocase &ri, 1888 const OffsetMap &offsets, 1889 const OffsetMap &other_offsets) const { 1890 return literal == ri.literal && 1891 offsets.at(target) == other_offsets.at(ri.target); 1892 } 1893 }; 1894 1895 class RoseInstrCheckMedLit 1896 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT, 1897 ROSE_STRUCT_CHECK_MED_LIT, 1898 RoseInstrCheckMedLit> { 1899 public: 1900 std::string literal; 1901 const RoseInstruction *target; 1902 RoseInstrCheckMedLit(std::string literal_in,const RoseInstruction * target_in)1903 explicit RoseInstrCheckMedLit(std::string literal_in, 1904 const RoseInstruction *target_in) 1905 : literal(std::move(literal_in)), target(target_in) {} 1906 1907 bool operator==(const RoseInstrCheckMedLit &ri) const { 1908 return literal == ri.literal && target == ri.target; 1909 } 1910 hash()1911 size_t hash() const override { 1912 return hash_all(opcode, literal); 1913 } 1914 1915 void write(void *dest, RoseEngineBlob &blob, 1916 const OffsetMap &offset_map) const override; 1917 equiv_to(const RoseInstrCheckMedLit & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1918 bool equiv_to(const RoseInstrCheckMedLit &ri, const OffsetMap &offsets, 1919 const OffsetMap &other_offsets) const { 1920 return literal == ri.literal && 1921 offsets.at(target) == other_offsets.at(ri.target); 1922 } 1923 }; 1924 1925 class RoseInstrCheckMedLitNocase 1926 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MED_LIT_NOCASE, 1927 ROSE_STRUCT_CHECK_MED_LIT_NOCASE, 1928 RoseInstrCheckMedLitNocase> { 1929 public: 1930 std::string literal; 1931 const RoseInstruction *target; 1932 RoseInstrCheckMedLitNocase(std::string literal_in,const RoseInstruction * target_in)1933 explicit RoseInstrCheckMedLitNocase(std::string literal_in, 1934 const RoseInstruction *target_in) 1935 : literal(std::move(literal_in)), target(target_in) { 1936 upperString(literal); 1937 } 1938 1939 bool operator==(const RoseInstrCheckMedLitNocase &ri) const { 1940 return literal == ri.literal && target == ri.target; 1941 } 1942 hash()1943 size_t hash() const override { 1944 return hash_all(opcode, literal); 1945 } 1946 1947 void write(void *dest, RoseEngineBlob &blob, 1948 const OffsetMap &offset_map) const override; 1949 equiv_to(const RoseInstrCheckMedLitNocase & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1950 bool equiv_to(const RoseInstrCheckMedLitNocase &ri, 1951 const OffsetMap &offsets, 1952 const OffsetMap &other_offsets) const { 1953 return literal == ri.literal && 1954 offsets.at(target) == other_offsets.at(ri.target); 1955 } 1956 }; 1957 1958 class RoseInstrClearWorkDone 1959 : public RoseInstrBaseTrivial<ROSE_INSTR_CLEAR_WORK_DONE, 1960 ROSE_STRUCT_CLEAR_WORK_DONE, 1961 RoseInstrClearWorkDone> { 1962 public: 1963 ~RoseInstrClearWorkDone() override; 1964 }; 1965 1966 class RoseInstrMultipathLookaround 1967 : public RoseInstrBaseOneTarget<ROSE_INSTR_MULTIPATH_LOOKAROUND, 1968 ROSE_STRUCT_MULTIPATH_LOOKAROUND, 1969 RoseInstrMultipathLookaround> { 1970 public: 1971 std::vector<std::vector<LookEntry>> multi_look; 1972 s32 last_start; 1973 std::array<u8, 16> start_mask; 1974 const RoseInstruction *target; 1975 RoseInstrMultipathLookaround(std::vector<std::vector<LookEntry>> ml,s32 last_start_in,std::array<u8,16> start_mask_in,const RoseInstruction * target_in)1976 RoseInstrMultipathLookaround(std::vector<std::vector<LookEntry>> ml, 1977 s32 last_start_in, 1978 std::array<u8, 16> start_mask_in, 1979 const RoseInstruction *target_in) 1980 : multi_look(std::move(ml)), last_start(last_start_in), 1981 start_mask(std::move(start_mask_in)), target(target_in) {} 1982 1983 bool operator==(const RoseInstrMultipathLookaround &ri) const { 1984 return multi_look == ri.multi_look && last_start == ri.last_start 1985 && start_mask == ri.start_mask && target == ri.target; 1986 } 1987 hash()1988 size_t hash() const override { 1989 return hash_all(opcode, multi_look, last_start, start_mask); 1990 } 1991 1992 void write(void *dest, RoseEngineBlob &blob, 1993 const OffsetMap &offset_map) const override; 1994 equiv_to(const RoseInstrMultipathLookaround & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)1995 bool equiv_to(const RoseInstrMultipathLookaround &ri, 1996 const OffsetMap &offsets, 1997 const OffsetMap &other_offsets) const { 1998 return multi_look == ri.multi_look && last_start == ri.last_start 1999 && start_mask == ri.start_mask 2000 && offsets.at(target) == other_offsets.at(ri.target); 2001 } 2002 }; 2003 2004 class RoseInstrCheckMultipathShufti16x8 2005 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_16x8, 2006 ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_16x8, 2007 RoseInstrCheckMultipathShufti16x8> { 2008 public: 2009 std::array<u8, 32> nib_mask; 2010 std::array<u8, 64> bucket_select_mask; 2011 std::array<u8, 64> data_select_mask; 2012 u16 hi_bits_mask; 2013 u16 lo_bits_mask; 2014 u16 neg_mask; 2015 s32 base_offset; 2016 s32 last_start; 2017 const RoseInstruction *target; 2018 RoseInstrCheckMultipathShufti16x8(std::array<u8,32> nib_mask_in,std::array<u8,64> bucket_select_mask_in,std::array<u8,64> data_select_mask_in,u16 hi_bits_mask_in,u16 lo_bits_mask_in,u16 neg_mask_in,s32 base_offset_in,s32 last_start_in,const RoseInstruction * target_in)2019 RoseInstrCheckMultipathShufti16x8(std::array<u8, 32> nib_mask_in, 2020 std::array<u8, 64> bucket_select_mask_in, 2021 std::array<u8, 64> data_select_mask_in, 2022 u16 hi_bits_mask_in, u16 lo_bits_mask_in, 2023 u16 neg_mask_in, s32 base_offset_in, 2024 s32 last_start_in, 2025 const RoseInstruction *target_in) 2026 : nib_mask(std::move(nib_mask_in)), 2027 bucket_select_mask(std::move(bucket_select_mask_in)), 2028 data_select_mask(std::move(data_select_mask_in)), 2029 hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in), 2030 neg_mask(neg_mask_in), base_offset(base_offset_in), 2031 last_start(last_start_in), target(target_in) {} 2032 2033 bool operator==(const RoseInstrCheckMultipathShufti16x8 &ri) const { 2034 return nib_mask == ri.nib_mask && 2035 bucket_select_mask == ri.bucket_select_mask && 2036 data_select_mask == ri.data_select_mask && 2037 hi_bits_mask == ri.hi_bits_mask && 2038 lo_bits_mask == ri.lo_bits_mask && 2039 neg_mask == ri.neg_mask && base_offset == ri.base_offset && 2040 last_start == ri.last_start && target == ri.target; 2041 } 2042 hash()2043 size_t hash() const override { 2044 return hash_all(opcode, nib_mask, bucket_select_mask, data_select_mask, 2045 hi_bits_mask, lo_bits_mask, neg_mask, base_offset, 2046 last_start); 2047 } 2048 2049 void write(void *dest, RoseEngineBlob &blob, 2050 const OffsetMap &offset_map) const override; 2051 equiv_to(const RoseInstrCheckMultipathShufti16x8 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)2052 bool equiv_to(const RoseInstrCheckMultipathShufti16x8 &ri, 2053 const OffsetMap &offsets, 2054 const OffsetMap &other_offsets) const { 2055 return nib_mask == ri.nib_mask && 2056 bucket_select_mask == ri.bucket_select_mask && 2057 data_select_mask == ri.data_select_mask && 2058 hi_bits_mask == ri.hi_bits_mask && 2059 lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask && 2060 base_offset == ri.base_offset && last_start == ri.last_start && 2061 offsets.at(target) == other_offsets.at(ri.target); 2062 } 2063 }; 2064 2065 class RoseInstrCheckMultipathShufti32x8 2066 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x8, 2067 ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x8, 2068 RoseInstrCheckMultipathShufti32x8> { 2069 public: 2070 std::array<u8, 32> hi_mask; 2071 std::array<u8, 32> lo_mask; 2072 std::array<u8, 64> bucket_select_mask; 2073 std::array<u8, 64> data_select_mask; 2074 u32 hi_bits_mask; 2075 u32 lo_bits_mask; 2076 u32 neg_mask; 2077 s32 base_offset; 2078 s32 last_start; 2079 const RoseInstruction *target; 2080 RoseInstrCheckMultipathShufti32x8(std::array<u8,32> hi_mask_in,std::array<u8,32> lo_mask_in,std::array<u8,64> bucket_select_mask_in,std::array<u8,64> data_select_mask_in,u32 hi_bits_mask_in,u32 lo_bits_mask_in,u32 neg_mask_in,s32 base_offset_in,s32 last_start_in,const RoseInstruction * target_in)2081 RoseInstrCheckMultipathShufti32x8(std::array<u8, 32> hi_mask_in, 2082 std::array<u8, 32> lo_mask_in, 2083 std::array<u8, 64> bucket_select_mask_in, 2084 std::array<u8, 64> data_select_mask_in, 2085 u32 hi_bits_mask_in, u32 lo_bits_mask_in, 2086 u32 neg_mask_in, s32 base_offset_in, 2087 s32 last_start_in, 2088 const RoseInstruction *target_in) 2089 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 2090 bucket_select_mask(std::move(bucket_select_mask_in)), 2091 data_select_mask(std::move(data_select_mask_in)), 2092 hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in), 2093 neg_mask(neg_mask_in), base_offset(base_offset_in), 2094 last_start(last_start_in), target(target_in) {} 2095 2096 bool operator==(const RoseInstrCheckMultipathShufti32x8 &ri) const { 2097 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2098 bucket_select_mask == ri.bucket_select_mask && 2099 data_select_mask == ri.data_select_mask && 2100 hi_bits_mask == ri.hi_bits_mask && 2101 lo_bits_mask == ri.lo_bits_mask && 2102 neg_mask == ri.neg_mask && base_offset == ri.base_offset && 2103 last_start == ri.last_start && target == ri.target; 2104 } 2105 hash()2106 size_t hash() const override { 2107 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, 2108 data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask, 2109 base_offset, last_start); 2110 } 2111 2112 void write(void *dest, RoseEngineBlob &blob, 2113 const OffsetMap &offset_map) const override; 2114 equiv_to(const RoseInstrCheckMultipathShufti32x8 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)2115 bool equiv_to(const RoseInstrCheckMultipathShufti32x8 &ri, 2116 const OffsetMap &offsets, 2117 const OffsetMap &other_offsets) const { 2118 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2119 bucket_select_mask == ri.bucket_select_mask && 2120 data_select_mask == ri.data_select_mask && 2121 hi_bits_mask == ri.hi_bits_mask && 2122 lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask && 2123 base_offset == ri.base_offset && last_start == ri.last_start && 2124 offsets.at(target) == other_offsets.at(ri.target); 2125 } 2126 }; 2127 2128 class RoseInstrCheckMultipathShufti32x16 2129 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_32x16, 2130 ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_32x16, 2131 RoseInstrCheckMultipathShufti32x16> { 2132 public: 2133 std::array<u8, 32> hi_mask; 2134 std::array<u8, 32> lo_mask; 2135 std::array<u8, 64> bucket_select_mask_hi; 2136 std::array<u8, 64> bucket_select_mask_lo; 2137 std::array<u8, 64> data_select_mask; 2138 u32 hi_bits_mask; 2139 u32 lo_bits_mask; 2140 u32 neg_mask; 2141 s32 base_offset; 2142 s32 last_start; 2143 const RoseInstruction *target; 2144 RoseInstrCheckMultipathShufti32x16(std::array<u8,32> hi_mask_in,std::array<u8,32> lo_mask_in,std::array<u8,64> bucket_select_mask_hi_in,std::array<u8,64> bucket_select_mask_lo_in,std::array<u8,64> data_select_mask_in,u32 hi_bits_mask_in,u32 lo_bits_mask_in,u32 neg_mask_in,s32 base_offset_in,s32 last_start_in,const RoseInstruction * target_in)2145 RoseInstrCheckMultipathShufti32x16(std::array<u8, 32> hi_mask_in, 2146 std::array<u8, 32> lo_mask_in, 2147 std::array<u8, 64> bucket_select_mask_hi_in, 2148 std::array<u8, 64> bucket_select_mask_lo_in, 2149 std::array<u8, 64> data_select_mask_in, 2150 u32 hi_bits_mask_in, u32 lo_bits_mask_in, 2151 u32 neg_mask_in, s32 base_offset_in, 2152 s32 last_start_in, 2153 const RoseInstruction *target_in) 2154 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 2155 bucket_select_mask_hi(std::move(bucket_select_mask_hi_in)), 2156 bucket_select_mask_lo(std::move(bucket_select_mask_lo_in)), 2157 data_select_mask(std::move(data_select_mask_in)), 2158 hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in), 2159 neg_mask(neg_mask_in), base_offset(base_offset_in), 2160 last_start(last_start_in), target(target_in) {} 2161 2162 bool operator==(const RoseInstrCheckMultipathShufti32x16 &ri) const { 2163 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2164 bucket_select_mask_hi == ri.bucket_select_mask_hi && 2165 bucket_select_mask_lo == ri.bucket_select_mask_lo && 2166 data_select_mask == ri.data_select_mask && 2167 hi_bits_mask == ri.hi_bits_mask && 2168 lo_bits_mask == ri.lo_bits_mask && 2169 neg_mask == ri.neg_mask && base_offset == ri.base_offset && 2170 last_start == ri.last_start && target == ri.target; 2171 } 2172 hash()2173 size_t hash() const override { 2174 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask_hi, 2175 bucket_select_mask_lo, data_select_mask, hi_bits_mask, 2176 lo_bits_mask, neg_mask, base_offset, last_start); 2177 } 2178 2179 void write(void *dest, RoseEngineBlob &blob, 2180 const OffsetMap &offset_map) const override; 2181 equiv_to(const RoseInstrCheckMultipathShufti32x16 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)2182 bool equiv_to(const RoseInstrCheckMultipathShufti32x16 &ri, 2183 const OffsetMap &offsets, 2184 const OffsetMap &other_offsets) const { 2185 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2186 bucket_select_mask_hi == ri.bucket_select_mask_hi && 2187 bucket_select_mask_lo == ri.bucket_select_mask_lo && 2188 data_select_mask == ri.data_select_mask && 2189 hi_bits_mask == ri.hi_bits_mask && 2190 lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask && 2191 base_offset == ri.base_offset && last_start == ri.last_start && 2192 offsets.at(target) == other_offsets.at(ri.target); 2193 } 2194 }; 2195 2196 class RoseInstrCheckMultipathShufti64 2197 : public RoseInstrBaseOneTarget<ROSE_INSTR_CHECK_MULTIPATH_SHUFTI_64, 2198 ROSE_STRUCT_CHECK_MULTIPATH_SHUFTI_64, 2199 RoseInstrCheckMultipathShufti64> { 2200 public: 2201 std::array<u8, 32> hi_mask; 2202 std::array<u8, 32> lo_mask; 2203 std::array<u8, 64> bucket_select_mask; 2204 std::array<u8, 64> data_select_mask; 2205 u64a hi_bits_mask; 2206 u64a lo_bits_mask; 2207 u64a neg_mask; 2208 s32 base_offset; 2209 s32 last_start; 2210 const RoseInstruction *target; 2211 RoseInstrCheckMultipathShufti64(std::array<u8,32> hi_mask_in,std::array<u8,32> lo_mask_in,std::array<u8,64> bucket_select_mask_in,std::array<u8,64> data_select_mask_in,u64a hi_bits_mask_in,u64a lo_bits_mask_in,u64a neg_mask_in,s32 base_offset_in,s32 last_start_in,const RoseInstruction * target_in)2212 RoseInstrCheckMultipathShufti64(std::array<u8, 32> hi_mask_in, 2213 std::array<u8, 32> lo_mask_in, 2214 std::array<u8, 64> bucket_select_mask_in, 2215 std::array<u8, 64> data_select_mask_in, 2216 u64a hi_bits_mask_in, u64a lo_bits_mask_in, 2217 u64a neg_mask_in, s32 base_offset_in, 2218 s32 last_start_in, 2219 const RoseInstruction *target_in) 2220 : hi_mask(std::move(hi_mask_in)), lo_mask(std::move(lo_mask_in)), 2221 bucket_select_mask(std::move(bucket_select_mask_in)), 2222 data_select_mask(std::move(data_select_mask_in)), 2223 hi_bits_mask(hi_bits_mask_in), lo_bits_mask(lo_bits_mask_in), 2224 neg_mask(neg_mask_in), base_offset(base_offset_in), 2225 last_start(last_start_in), target(target_in) {} 2226 2227 bool operator==(const RoseInstrCheckMultipathShufti64 &ri) const { 2228 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2229 bucket_select_mask == ri.bucket_select_mask && 2230 data_select_mask == ri.data_select_mask && 2231 hi_bits_mask == ri.hi_bits_mask && 2232 lo_bits_mask == ri.lo_bits_mask && 2233 neg_mask == ri.neg_mask && base_offset == ri.base_offset && 2234 last_start == ri.last_start && target == ri.target; 2235 } 2236 hash()2237 size_t hash() const override { 2238 return hash_all(opcode, hi_mask, lo_mask, bucket_select_mask, 2239 data_select_mask, hi_bits_mask, lo_bits_mask, neg_mask, 2240 base_offset, last_start); 2241 } 2242 2243 void write(void *dest, RoseEngineBlob &blob, 2244 const OffsetMap &offset_map) const override; 2245 equiv_to(const RoseInstrCheckMultipathShufti64 & ri,const OffsetMap & offsets,const OffsetMap & other_offsets)2246 bool equiv_to(const RoseInstrCheckMultipathShufti64 &ri, 2247 const OffsetMap &offsets, 2248 const OffsetMap &other_offsets) const { 2249 return hi_mask == ri.hi_mask && lo_mask == ri.lo_mask && 2250 bucket_select_mask == ri.bucket_select_mask && 2251 data_select_mask == ri.data_select_mask && 2252 hi_bits_mask == ri.hi_bits_mask && 2253 lo_bits_mask == ri.lo_bits_mask && neg_mask == ri.neg_mask && 2254 base_offset == ri.base_offset && last_start == ri.last_start && 2255 offsets.at(target) == other_offsets.at(ri.target); 2256 } 2257 }; 2258 2259 class RoseInstrIncludedJump 2260 : public RoseInstrBaseNoTargets<ROSE_INSTR_INCLUDED_JUMP, 2261 ROSE_STRUCT_INCLUDED_JUMP, 2262 RoseInstrIncludedJump> { 2263 public: 2264 u32 child_offset; 2265 u8 squash; 2266 RoseInstrIncludedJump(u32 child_offset_in,u8 squash_in)2267 RoseInstrIncludedJump(u32 child_offset_in, u8 squash_in) 2268 : child_offset(child_offset_in), squash(squash_in) {} 2269 2270 bool operator==(const RoseInstrIncludedJump &ri) const { 2271 return child_offset == ri.child_offset && squash == ri.squash; 2272 } 2273 hash()2274 size_t hash() const override { 2275 return hash_all(static_cast<int>(opcode), child_offset, squash); 2276 } 2277 2278 void write(void *dest, RoseEngineBlob &blob, 2279 const OffsetMap &offset_map) const override; 2280 equiv_to(const RoseInstrIncludedJump & ri,const OffsetMap &,const OffsetMap &)2281 bool equiv_to(const RoseInstrIncludedJump &ri, const OffsetMap &, 2282 const OffsetMap &) const { 2283 return child_offset == ri.child_offset && squash == ri.squash; 2284 } 2285 }; 2286 2287 class RoseInstrSetLogical 2288 : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_LOGICAL, 2289 ROSE_STRUCT_SET_LOGICAL, 2290 RoseInstrSetLogical> { 2291 public: 2292 u32 lkey; 2293 s32 offset_adjust; 2294 RoseInstrSetLogical(u32 lkey_in,s32 offset_adjust_in)2295 RoseInstrSetLogical(u32 lkey_in, s32 offset_adjust_in) 2296 : lkey(lkey_in), offset_adjust(offset_adjust_in) {} 2297 2298 bool operator==(const RoseInstrSetLogical &ri) const { 2299 return lkey == ri.lkey && offset_adjust == ri.offset_adjust; 2300 } 2301 hash()2302 size_t hash() const override { 2303 return hash_all(opcode, lkey, offset_adjust); 2304 } 2305 2306 void write(void *dest, RoseEngineBlob &blob, 2307 const OffsetMap &offset_map) const override; 2308 equiv_to(const RoseInstrSetLogical & ri,const OffsetMap &,const OffsetMap &)2309 bool equiv_to(const RoseInstrSetLogical &ri, const OffsetMap &, 2310 const OffsetMap &) const { 2311 return lkey == ri.lkey && offset_adjust == ri.offset_adjust; 2312 } 2313 }; 2314 2315 class RoseInstrSetCombination 2316 : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_COMBINATION, 2317 ROSE_STRUCT_SET_COMBINATION, 2318 RoseInstrSetCombination> { 2319 public: 2320 u32 ckey; 2321 RoseInstrSetCombination(u32 ckey_in)2322 RoseInstrSetCombination(u32 ckey_in) : ckey(ckey_in) {} 2323 2324 bool operator==(const RoseInstrSetCombination &ri) const { 2325 return ckey == ri.ckey; 2326 } 2327 hash()2328 size_t hash() const override { 2329 return hash_all(opcode, ckey); 2330 } 2331 2332 void write(void *dest, RoseEngineBlob &blob, 2333 const OffsetMap &offset_map) const override; 2334 equiv_to(const RoseInstrSetCombination & ri,const OffsetMap &,const OffsetMap &)2335 bool equiv_to(const RoseInstrSetCombination &ri, const OffsetMap &, 2336 const OffsetMap &) const { 2337 return ckey == ri.ckey; 2338 } 2339 }; 2340 2341 class RoseInstrFlushCombination 2342 : public RoseInstrBaseTrivial<ROSE_INSTR_FLUSH_COMBINATION, 2343 ROSE_STRUCT_FLUSH_COMBINATION, 2344 RoseInstrFlushCombination> { 2345 public: 2346 ~RoseInstrFlushCombination() override; 2347 }; 2348 2349 class RoseInstrLastFlushCombination 2350 : public RoseInstrBaseTrivial<ROSE_INSTR_LAST_FLUSH_COMBINATION, 2351 ROSE_STRUCT_LAST_FLUSH_COMBINATION, 2352 RoseInstrLastFlushCombination> { 2353 public: 2354 ~RoseInstrLastFlushCombination() override; 2355 }; 2356 2357 class RoseInstrSetExhaust 2358 : public RoseInstrBaseNoTargets<ROSE_INSTR_SET_EXHAUST, 2359 ROSE_STRUCT_SET_EXHAUST, 2360 RoseInstrSetExhaust> { 2361 public: 2362 u32 ekey; 2363 RoseInstrSetExhaust(u32 ekey_in)2364 RoseInstrSetExhaust(u32 ekey_in) : ekey(ekey_in) {} 2365 2366 bool operator==(const RoseInstrSetExhaust &ri) const { 2367 return ekey == ri.ekey; 2368 } 2369 hash()2370 size_t hash() const override { 2371 return hash_all(opcode, ekey); 2372 } 2373 2374 void write(void *dest, RoseEngineBlob &blob, 2375 const OffsetMap &offset_map) const override; 2376 equiv_to(const RoseInstrSetExhaust & ri,const OffsetMap &,const OffsetMap &)2377 bool equiv_to(const RoseInstrSetExhaust &ri, const OffsetMap &, 2378 const OffsetMap &) const { 2379 return ekey == ri.ekey; 2380 } 2381 }; 2382 2383 class RoseInstrEnd 2384 : public RoseInstrBaseTrivial<ROSE_INSTR_END, ROSE_STRUCT_END, 2385 RoseInstrEnd> { 2386 public: 2387 ~RoseInstrEnd() override; 2388 }; 2389 2390 } 2391 #endif 2392