Skip to content

Commit

Permalink
Fix StubLinkerCPU::EmitMovConstant (dotnet#53510)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
janvorli committed Jun 1, 2021
1 parent b802263 commit 92db46e
Showing 1 changed file with 13 additions and 17 deletions.
30 changes: 13 additions & 17 deletions src/coreclr/vm/arm64/stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 92db46e

Please sign in to comment.