* Tactic T3 (single-byte instruction): evict a neighbour instruction. */
| 555 | * Tactic T3 (single-byte instruction): evict a neighbour instruction. |
| 556 | */ |
| 557 | static Patch *tactic_T3b(Binary &B, Instr *I, const Trampoline *T) |
| 558 | { |
| 559 | // We can still use T3 on single-byte instructions, only if the next |
| 560 | // byte interpreted as a short jmp rel8 happens to land in a suitable |
| 561 | // location. |
| 562 | |
| 563 | if (I->size != 1 || !option_tactic_T3 || !canPatch(I)) |
| 564 | return nullptr; |
| 565 | Instr *J = I->succ(); |
| 566 | if (J == nullptr) |
| 567 | return nullptr; |
| 568 | switch (J->STATE[0]) |
| 569 | { |
| 570 | case STATE_INSTRUCTION: case STATE_FREE: |
| 571 | break; |
| 572 | default: |
| 573 | return nullptr; |
| 574 | } |
| 575 | int8_t rel8 = (int8_t)J->PATCH[0]; |
| 576 | if (!option_tactic_backward_T3 && rel8 < 1) |
| 577 | return nullptr; |
| 578 | intptr_t target = I->addr + /*sizeof(short jmp)=*/2 + (intptr_t)rel8; |
| 579 | if (target >= I->addr) |
| 580 | { |
| 581 | for (; J != nullptr && J->addr + J->size <= target; J = J->next()) |
| 582 | ; |
| 583 | } |
| 584 | else |
| 585 | { |
| 586 | for (J = I->prev(); J != nullptr && J->addr > target; J = J->prev()) |
| 587 | ; |
| 588 | } |
| 589 | if (J == nullptr || target <= J->addr || |
| 590 | (J->addr < I->addr && J->addr + J->size > I->addr)) |
| 591 | return nullptr; |
| 592 | unsigned i = target - J->addr; |
| 593 | uint8_t state = J->STATE[i]; |
| 594 | Patch *P = nullptr; |
| 595 | const Alloc *A = nullptr; |
| 596 | switch (state) |
| 597 | { |
| 598 | case STATE_INSTRUCTION: |
| 599 | case STATE_FREE: |
| 600 | { |
| 601 | bool save = (bool)J->no_optimize; |
| 602 | if (target < I->addr) |
| 603 | J->no_optimize = true; |
| 604 | A = allocatePunnedJump(B, J, i, I, T); |
| 605 | if (A == nullptr) |
| 606 | { |
| 607 | J->no_optimize = save; |
| 608 | return nullptr; |
| 609 | } |
| 610 | P = new Patch(J, TACTIC_T3, A); |
| 611 | patchJump(P, i); |
| 612 | if (state == STATE_FREE) |
| 613 | { |
| 614 | // J is already patched. so we are done. |