From 8ae76a6680686145946c0da71c59b33ba6e615cb Mon Sep 17 00:00:00 2001 From: Jonathan Hamilton Date: Sat, 9 Dec 2017 13:14:38 -0800 Subject: [PATCH] Fix arm64 MOVI2R for addresses between 2gb and 4gb offset from PC The PC offset ADRP() path takes a s32 value, but the input offset was being tested as abs(ptr) < 0xFFFFFFFF. This caused values between 0x80000000 and 0xFFFFFFFF to incorrectly use this path, despite the offsets not being representable in an s32. This caused a crash in the VertexLoader on android 8.1 immediate in wind waker (and possibly all other apps on android 8.1) as the jit and data sections happened to be loaded 4gb apart in virtual memory, causing some pointers to hit this --- Source/Core/Common/Arm64Emitter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp index ed1fa2b626..fe8993b354 100644 --- a/Source/Core/Common/Arm64Emitter.cpp +++ b/Source/Core/Common/Arm64Emitter.cpp @@ -2029,7 +2029,8 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize) u64 aligned_pc = (u64)GetCodePtr() & ~0xFFF; s64 aligned_offset = (s64)imm - (s64)aligned_pc; - if (upload_part.Count() > 1 && std::abs(aligned_offset) < 0xFFFFFFFFLL) + // The offset for ADR/ADRP is an s32, so make sure it can be represented in that + if (upload_part.Count() > 1 && std::abs(aligned_offset) < 0x7FFFFFFFLL) { // Immediate we are loading is within 4GB of our aligned range // Most likely a address that we can load in one or two instructions