| 618 | } |
| 619 | |
| 620 | static bool HandleAtomicVectorStore(uint32_t Instr, uintptr_t ProgramCounter) { |
| 621 | uint32_t* PC = (uint32_t*)ProgramCounter; |
| 622 | |
| 623 | uint32_t Size = (Instr >> 30) & 1; |
| 624 | uint32_t DataReg = Instr & 0x1F; |
| 625 | |
| 626 | if (Size == 1) { |
| 627 | // 64-bit pair happens on paranoid vector stores |
| 628 | // [0] ldaxp(xzr, TMP3, MemSrc); // <- Can hit SIGBUS. Overwritten with DMB |
| 629 | // [1] stlxp(TMP3, TMP1, TMP2, MemSrc); // <- Can also hit SIGBUS |
| 630 | // [2] cbnz(TMP3, &B); // < Overwritten with DMB |
| 631 | if (DataReg == 31) { |
| 632 | uint32_t NextInstr = PC[1]; |
| 633 | uint32_t AddrReg = (NextInstr >> 5) & 0x1F; |
| 634 | DataReg = NextInstr & 0x1F; |
| 635 | uint32_t DataReg2 = (NextInstr >> 10) & 0x1F; |
| 636 | uint32_t STP = (0b10 << 30) | (0b101001000000000 << 15) | (DataReg2 << 10) | (AddrReg << 5) | DataReg; |
| 637 | |
| 638 | PC[0] = DMB; |
| 639 | PC[1] = STP; |
| 640 | PC[2] = DMB; |
| 641 | // Back up one instruction and have another go |
| 642 | ClearICache(&PC[0], 12); |
| 643 | return true; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | return false; |
| 648 | } |
| 649 | |
| 650 | template<typename T> |
| 651 | using CASExpectedFn = T (*)(T Src, T Expected); |
no test coverage detected