Skip to content

Commit 62a5da2

Browse files
committed
Make test x86-64-gotpc-relax-nopic.s pass
1 parent 4bf2ab0 commit 62a5da2

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

lld/ELF/Arch/X86_64.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
901901
static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
902902
uint8_t modRm) {
903903
const uint8_t rex = loc[-3];
904+
const bool isRex2 = loc[-4] == 0xd5;
904905
// Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
905906
if (op == 0x85) {
906907
// See "TEST-Logical Compare" (4-428 Vol. 2B),
@@ -925,7 +926,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
925926
// See "TEST-Logical Compare" (4-428 Vol. 2B).
926927
loc[-2] = 0xf7;
927928

928-
// Move R bit to the B bit in REX byte.
929+
// Move R bit to the B bit in REX/REX2 byte.
929930
// REX byte is encoded as 0100WRXB, where
930931
// 0100 is 4bit fixed pattern.
931932
// REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
@@ -936,7 +937,18 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
936937
// REX.B This 1-bit value is an extension to the MODRM.rm field or the
937938
// SIB.base field.
938939
// See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
939-
loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
940+
//
941+
// REX2 prefix is encoded as 0xd5|M|R2|X2|B2|WRXB, where
942+
// 0xd5 is 1byte fixed pattern.
943+
// REX2's [W,R,X,B] have the same meanings as REX's.
944+
// REX2.M encodes the map id.
945+
// R2/X2/B2 provides the fifth and most siginicant bits of the R/X/B
946+
// register identifiers, each of which can now address all 32 GPRs.
947+
// TODO: Add the section number here after APX SPEC is merged into SDM.
948+
if (isRex2)
949+
loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2;
950+
else
951+
loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
940952
write32le(loc, val);
941953
return;
942954
}
@@ -957,7 +969,10 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
957969
// "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
958970
// descriptions about each operation.
959971
loc[-2] = 0x81;
960-
loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
972+
if (isRex2)
973+
loc[-3] = (rex & ~0x44) | (rex & 0x44) >> 2;
974+
else
975+
loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
961976
write32le(loc, val);
962977
}
963978

0 commit comments

Comments
 (0)