| 879 | } |
| 880 | |
| 881 | void OpDispatchBuilder::JUMPOp(OpcodeArgs) { |
| 882 | // Calculate flags early. |
| 883 | CalculateDeferredFlags(); |
| 884 | |
| 885 | BlockSetRIP = true; |
| 886 | |
| 887 | // Jump instruction only uses up to 32-bit signed displacement |
| 888 | int64_t TargetOffset = Op->Src[0].Literal(); |
| 889 | uint64_t InstRIP = Op->PC + Op->InstSize; |
| 890 | uint64_t TargetRIP = InstRIP + TargetOffset; |
| 891 | |
| 892 | if (GetGPROpSize() == OpSize::i32Bit) { |
| 893 | // If the GPRSize is 4 then we need to be careful about PC wrapping |
| 894 | if (TargetOffset < 0 && -TargetOffset > InstRIP) { |
| 895 | // Invert the signed value if we are underflowing |
| 896 | TargetOffset = 0x1'0000'0000ULL + TargetOffset; |
| 897 | } else if (TargetOffset >= 0 && TargetRIP >= 0x1'0000'0000ULL) { |
| 898 | // We are overflowing, wrap around |
| 899 | TargetOffset = TargetOffset - 0x1'0000'0000ULL; |
| 900 | } |
| 901 | |
| 902 | TargetRIP &= 0xFFFFFFFFU; |
| 903 | } |
| 904 | |
| 905 | CalculateDeferredFlags(); |
| 906 | // This is just an unconditional relative literal jump |
| 907 | if (Multiblock) { |
| 908 | auto JumpBlock = JumpTargets.find(TargetRIP); |
| 909 | if (JumpBlock != JumpTargets.end()) { |
| 910 | Jump(GetNewJumpBlock(TargetRIP)); |
| 911 | } else { |
| 912 | // If the block isn't a jump target then we need to create an exit block |
| 913 | auto Jump_ = Jump(); |
| 914 | |
| 915 | // Place after this block for fallthrough behavior |
| 916 | auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); |
| 917 | SetJumpTarget(Jump_, JumpTarget); |
| 918 | SetCurrentCodeBlock(JumpTarget); |
| 919 | StartNewBlock(); |
| 920 | ExitRelocatedPC(Op, TargetOffset); |
| 921 | } |
| 922 | } else { |
| 923 | ExitRelocatedPC(Op, TargetOffset); |
| 924 | } |
| 925 | } |
| 926 | |
| 927 | void OpDispatchBuilder::JUMPAbsoluteOp(OpcodeArgs) { |
| 928 | // Calculate flags early. |