Fix pointer authentication modifier source register (#61)
Pointer authentication instructions allow the stack pointer as source for the
modifier, but simulation was using the zero register instead. Fix this and
add a regression test.
diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc
index 1830eb4..838c579 100644
--- a/src/aarch64/simulator-aarch64.cc
+++ b/src/aarch64/simulator-aarch64.cc
@@ -5239,18 +5239,18 @@
unsigned src = instr->GetRn();
switch (instr->Mask(DataProcessing1SourceMask)) {
-#define DEFINE_PAUTH_FUNCS(SUFFIX, KEY, D) \
- case PAC##SUFFIX: { \
- uint64_t mod = ReadXRegister(src); \
- uint64_t ptr = ReadXRegister(dst); \
- WriteXRegister(dst, AddPAC(ptr, mod, KEY, D)); \
- break; \
- } \
- case AUT##SUFFIX: { \
- uint64_t mod = ReadXRegister(src); \
- uint64_t ptr = ReadXRegister(dst); \
- WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \
- break; \
+#define DEFINE_PAUTH_FUNCS(SUFFIX, KEY, D) \
+ case PAC##SUFFIX: { \
+ uint64_t mod = ReadXRegister(src, Reg31IsStackPointer); \
+ uint64_t ptr = ReadXRegister(dst); \
+ WriteXRegister(dst, AddPAC(ptr, mod, KEY, D)); \
+ break; \
+ } \
+ case AUT##SUFFIX: { \
+ uint64_t mod = ReadXRegister(src, Reg31IsStackPointer); \
+ uint64_t ptr = ReadXRegister(dst); \
+ WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \
+ break; \
}
PAUTH_MODES_REGISTER_CONTEXT(DEFINE_PAUTH_FUNCS)
diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc
index a1543a7..ac701c3 100644
--- a/test/aarch64/test-assembler-aarch64.cc
+++ b/test/aarch64/test-assembler-aarch64.cc
@@ -1916,6 +1916,34 @@
}
}
+TEST(pac_sp_modifier) {
+ SETUP_WITH_FEATURES(CPUFeatures::kPAuth);
+
+ START();
+
+ __ Mov(x0, 0x0000000012345678);
+ __ Mov(x1, x0);
+ __ Mov(x10, sp);
+
+ // Generate PACs using sp and register containing a copy of sp.
+ __ Pacia(x0, x10);
+ __ Pacia(x1, sp);
+
+ // Authenticate the pointers, exchanging (equal) modifiers.
+ __ Mov(x2, x0);
+ __ Mov(x3, x1);
+ __ Autia(x2, sp);
+ __ Autia(x3, x10);
+
+ END();
+
+ if (CAN_RUN()) {
+ RUN();
+
+ ASSERT_EQUAL_64(x0, x1);
+ ASSERT_EQUAL_64(x2, x3);
+ }
+}
TEST(label) {
SETUP();