| 1031 | } |
| 1032 | |
| 1033 | Decoder::DecodedBlockStatus Decoder::DecodeInstruction(uint64_t PC) { |
| 1034 | // Will be set if DecodeInstructionImpl tries to read non-executable memory |
| 1035 | HitNonExecutableRange = false; |
| 1036 | bool ErrorDuringDecoding = !DecodeInstructionImpl(PC); |
| 1037 | |
| 1038 | if (ErrorDuringDecoding || HitNonExecutableRange) [[unlikely]] { |
| 1039 | // Put an invalid instruction in the stream so the core can raise SIGILL if hit |
| 1040 | // Error while decoding instruction. We don't know the table or instruction size |
| 1041 | DecodeInst->TableInfo = nullptr; |
| 1042 | DecodeInst->InstSize = 0; |
| 1043 | return ErrorDuringDecoding ? DecodedBlockStatus::INVALID_INST : DecodedBlockStatus::NOEXEC_INST; |
| 1044 | } else if (!DecodeInst->TableInfo || (DecodeInst->TableInfo->Type == TYPE_INST && !DecodeInst->TableInfo->OpcodeDispatcher.OpDispatch)) { |
| 1045 | // If there wasn't an error during decoding but we have no dispatcher for the instruction then claim invalid instruction. |
| 1046 | return DecodedBlockStatus::INVALID_INST; |
| 1047 | } |
| 1048 | |
| 1049 | if (CTX->AreMonoHacksActive()) { |
| 1050 | // Unity uses a standard SPSC ringbuffer with cached read/write pointers and thread waiting flags at the following |
| 1051 | // offsets, which are consistent between 32-bit and 64-bit Unity versions from 2015 onwards. |
| 1052 | auto IsKnownAtomicDisplacement = [](uint64_t Displacement) { |
| 1053 | return Displacement == 0x80 || Displacement == 0x84 || Displacement == 0xC0 || Displacement == 0xC4; |
| 1054 | }; |
| 1055 | |
| 1056 | if (DecodeInst->OP == 0x8b && DecodeInst->Src[0].IsGPRIndirect() && |
| 1057 | IsKnownAtomicDisplacement(DecodeInst->Src[0].Data.GPRIndirect.Displacement)) { |
| 1058 | DecodeInst->ForceTSO = true; |
| 1059 | } |
| 1060 | if (DecodeInst->OP == 0x89 && DecodeInst->Dest.IsGPRIndirect() && IsKnownAtomicDisplacement(DecodeInst->Dest.Data.GPRIndirect.Displacement)) { |
| 1061 | DecodeInst->ForceTSO = true; |
| 1062 | } |
| 1063 | } |
| 1064 | |
| 1065 | return DecodedBlockStatus::SUCCESS; |
| 1066 | } |
| 1067 | |
| 1068 | void Decoder::BranchTargetInMultiblockRange() { |
| 1069 | if (!CTX->Config.Multiblock) { |
nothing calls this directly
no test coverage detected