From: Jan Vorlicek Date: Tue, 1 Jun 2021 04:59:48 +0000 (+0200) Subject: Fix StubLinkerCPU::EmitMovConstant (#53510) X-Git-Tag: submit/tizen/20210909.063632~1070 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92db46e0fefbf9a5713bb487648b99949aa8ce30;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Fix StubLinkerCPU::EmitMovConstant (#53510) The method has a bug that caused it to early out for constants with lowest 16, 24 or 32 bit being zero. The checks are inverse. This issue caused failures in System.CodeDom.Tests after my change that changed code heaps and resulted in the allocations starting at 64kB aligned address. The failure could happen even before my change, but extremely rarely, depending on where the heap virtual memory is located. This change fixes the problem. --- diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index acacdf8..bfff364 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -1331,23 +1331,19 @@ void StubLinkerCPU::EmitMovConstant(IntReg target, UINT64 constant) // MOVK Rd, <2nd word>, LSL 1 // MOVK Rd, <3nd word>, LSL 2 // MOVK Rd, <4nd word>, LSL 3 - WORD word = (WORD) (constant & WORD_MASK); - Emit32((DWORD)(0xD2<<24 | (4)<<21 | word<<5 | target)); - if (!(constant & 0xFFFF)) return; - - word = (WORD) ((constant>>16) & WORD_MASK); - if (word != 0) - Emit32((DWORD)(0xF2<<24 | (5)<<21 | word<<5 | target)); - if (!(constant & 0xFFFFFFFF)) return; - - word = (WORD) ((constant>>32) & WORD_MASK); - if (word != 0) - Emit32((DWORD)(0xF2<<24 | (6)<<21 | word<<5 | target)); - if (!(constant & 0xFFFFFFFFFFFF)) return; - - word = (WORD) ((constant>>48) & WORD_MASK); - if (word != 0) - Emit32((DWORD)(0xF2<<24 | (7)<<21 | word<<5 | target)); + + DWORD movInstr = 0xD2; // MOVZ + int shift = 0; + do + { + WORD word = (WORD) (constant & WORD_MASK); + Emit32((DWORD)(movInstr<<24 | (1 << 23) | (shift)<<21 | word<<5 | target)); + shift++; + movInstr = 0xF2; // MOVK + } + while ((constant >>= 16) != 0); + + #undef WORD_MASK }