Add a ppc64le ABI tester.

Now we have ABI tests for every architecture where we have assembly.

Change-Id: I59bc2d0f72f2325e9f294b1fc08287bb93fc9cd2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39008
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 427bc64..c6073d2 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -118,6 +118,14 @@
   )
 endif()
 
+if(${ARCH} STREQUAL "ppc64le")
+  set(
+    CRYPTO_ARCH_SOURCES
+
+    test/trampoline-ppc.${ASM_EXT}
+  )
+endif()
+
 if(${ARCH} STREQUAL "x86")
   set(
     CRYPTO_ARCH_SOURCES
@@ -147,6 +155,7 @@
 perlasm(cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} cipher_extra/asm/chacha20_poly1305_x86_64.pl)
 perlasm(test/trampoline-armv4.${ASM_EXT} test/asm/trampoline-armv4.pl)
 perlasm(test/trampoline-armv8.${ASM_EXT} test/asm/trampoline-armv8.pl)
+perlasm(test/trampoline-ppc.${ASM_EXT} test/asm/trampoline-ppc.pl)
 perlasm(test/trampoline-x86.${ASM_EXT} test/asm/trampoline-x86.pl)
 perlasm(test/trampoline-x86_64.${ASM_EXT} test/asm/trampoline-x86_64.pl)
 
diff --git a/crypto/abi_self_test.cc b/crypto/abi_self_test.cc
index 1fcf6bc..c48818b 100644
--- a/crypto/abi_self_test.cc
+++ b/crypto/abi_self_test.cc
@@ -341,7 +341,6 @@
 }
 #endif   // OPENSSL_ARM && SUPPORTS_ABI_TEST
 
-
 #if defined(OPENSSL_AARCH64) && defined(SUPPORTS_ABI_TEST)
 extern "C" {
 void abi_test_clobber_x0(void);
@@ -521,3 +520,289 @@
   CHECK_ABI_NO_UNWIND(abi_test_clobber_v15_upper);
 }
 #endif   // OPENSSL_AARCH64 && SUPPORTS_ABI_TEST
+
+#if defined(OPENSSL_PPC64LE) && defined(SUPPORTS_ABI_TEST)
+extern "C" {
+void abi_test_clobber_r0(void);
+// r1 is the stack pointer.
+void abi_test_clobber_r2(void);
+void abi_test_clobber_r3(void);
+void abi_test_clobber_r4(void);
+void abi_test_clobber_r5(void);
+void abi_test_clobber_r6(void);
+void abi_test_clobber_r7(void);
+void abi_test_clobber_r8(void);
+void abi_test_clobber_r9(void);
+void abi_test_clobber_r10(void);
+void abi_test_clobber_r11(void);
+void abi_test_clobber_r12(void);
+// r13 is the thread pointer.
+void abi_test_clobber_r14(void);
+void abi_test_clobber_r15(void);
+void abi_test_clobber_r16(void);
+void abi_test_clobber_r17(void);
+void abi_test_clobber_r18(void);
+void abi_test_clobber_r19(void);
+void abi_test_clobber_r20(void);
+void abi_test_clobber_r21(void);
+void abi_test_clobber_r22(void);
+void abi_test_clobber_r23(void);
+void abi_test_clobber_r24(void);
+void abi_test_clobber_r25(void);
+void abi_test_clobber_r26(void);
+void abi_test_clobber_r27(void);
+void abi_test_clobber_r28(void);
+void abi_test_clobber_r29(void);
+void abi_test_clobber_r30(void);
+void abi_test_clobber_r31(void);
+
+void abi_test_clobber_f0(void);
+void abi_test_clobber_f1(void);
+void abi_test_clobber_f2(void);
+void abi_test_clobber_f3(void);
+void abi_test_clobber_f4(void);
+void abi_test_clobber_f5(void);
+void abi_test_clobber_f6(void);
+void abi_test_clobber_f7(void);
+void abi_test_clobber_f8(void);
+void abi_test_clobber_f9(void);
+void abi_test_clobber_f10(void);
+void abi_test_clobber_f11(void);
+void abi_test_clobber_f12(void);
+void abi_test_clobber_f13(void);
+void abi_test_clobber_f14(void);
+void abi_test_clobber_f15(void);
+void abi_test_clobber_f16(void);
+void abi_test_clobber_f17(void);
+void abi_test_clobber_f18(void);
+void abi_test_clobber_f19(void);
+void abi_test_clobber_f20(void);
+void abi_test_clobber_f21(void);
+void abi_test_clobber_f22(void);
+void abi_test_clobber_f23(void);
+void abi_test_clobber_f24(void);
+void abi_test_clobber_f25(void);
+void abi_test_clobber_f26(void);
+void abi_test_clobber_f27(void);
+void abi_test_clobber_f28(void);
+void abi_test_clobber_f29(void);
+void abi_test_clobber_f30(void);
+void abi_test_clobber_f31(void);
+
+void abi_test_clobber_v0(void);
+void abi_test_clobber_v1(void);
+void abi_test_clobber_v2(void);
+void abi_test_clobber_v3(void);
+void abi_test_clobber_v4(void);
+void abi_test_clobber_v5(void);
+void abi_test_clobber_v6(void);
+void abi_test_clobber_v7(void);
+void abi_test_clobber_v8(void);
+void abi_test_clobber_v9(void);
+void abi_test_clobber_v10(void);
+void abi_test_clobber_v11(void);
+void abi_test_clobber_v12(void);
+void abi_test_clobber_v13(void);
+void abi_test_clobber_v14(void);
+void abi_test_clobber_v15(void);
+void abi_test_clobber_v16(void);
+void abi_test_clobber_v17(void);
+void abi_test_clobber_v18(void);
+void abi_test_clobber_v19(void);
+void abi_test_clobber_v20(void);
+void abi_test_clobber_v21(void);
+void abi_test_clobber_v22(void);
+void abi_test_clobber_v23(void);
+void abi_test_clobber_v24(void);
+void abi_test_clobber_v25(void);
+void abi_test_clobber_v26(void);
+void abi_test_clobber_v27(void);
+void abi_test_clobber_v28(void);
+void abi_test_clobber_v29(void);
+void abi_test_clobber_v30(void);
+void abi_test_clobber_v31(void);
+
+void abi_test_clobber_cr0(void);
+void abi_test_clobber_cr1(void);
+void abi_test_clobber_cr2(void);
+void abi_test_clobber_cr3(void);
+void abi_test_clobber_cr4(void);
+void abi_test_clobber_cr5(void);
+void abi_test_clobber_cr6(void);
+void abi_test_clobber_cr7(void);
+
+void abi_test_clobber_ctr(void);
+void abi_test_clobber_lr(void);
+
+}  // extern "C"
+
+TEST(ABITest, PPC64LE) {
+  // abi_test_trampoline hides unsaved registers from the caller, so we can
+  // safely call the abi_test_clobber_* functions below.
+  abi_test::internal::CallerState state;
+  RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
+  CHECK_ABI_NO_UNWIND(abi_test_trampoline,
+                      reinterpret_cast<crypto_word_t>(abi_test_clobber_r14),
+                      &state, nullptr, 0, 0 /* no breakpoint */);
+
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r0);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r2);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r3);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r4);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r5);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r6);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r7);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r8);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r9);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r10);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r11);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_r12);
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r14),
+                          "r14 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r15),
+                          "r15 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r16),
+                          "r16 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r17),
+                          "r17 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r18),
+                          "r18 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r19),
+                          "r19 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r20),
+                          "r20 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r21),
+                          "r21 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r22),
+                          "r22 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r23),
+                          "r23 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r24),
+                          "r24 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r25),
+                          "r25 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r26),
+                          "r26 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r27),
+                          "r27 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r28),
+                          "r28 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r29),
+                          "r29 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r30),
+                          "r30 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r31),
+                          "r31 was not restored after return");
+
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f0);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f1);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f2);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f3);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f4);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f5);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f6);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f7);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f8);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f9);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f10);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f11);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f12);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_f13);
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f14),
+                          "f14 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f15),
+                          "f15 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f16),
+                          "f16 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f17),
+                          "f17 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f18),
+                          "f18 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f19),
+                          "f19 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f20),
+                          "f20 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f21),
+                          "f21 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f22),
+                          "f22 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f23),
+                          "f23 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f24),
+                          "f24 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f25),
+                          "f25 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f26),
+                          "f26 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f27),
+                          "f27 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f28),
+                          "f28 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f29),
+                          "f29 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f30),
+                          "f30 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_f31),
+                          "f31 was not restored after return");
+
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v0);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v1);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v2);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v3);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v4);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v5);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v6);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v7);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v8);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v9);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v10);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v11);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v12);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v13);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v14);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v15);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v16);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v17);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v18);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_v19);
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v20),
+                          "v20 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v21),
+                          "v21 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v22),
+                          "v22 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v23),
+                          "v23 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v24),
+                          "v24 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v25),
+                          "v25 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v26),
+                          "v26 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v27),
+                          "v27 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v28),
+                          "v28 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v29),
+                          "v29 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v30),
+                          "v30 was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_v31),
+                          "v31 was not restored after return");
+
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_cr0);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_cr1);
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr2),
+                          "cr was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr3),
+                          "cr was not restored after return");
+  EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_cr4),
+                          "cr was not restored after return");
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_cr5);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_cr6);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_cr7);
+
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_ctr);
+  CHECK_ABI_NO_UNWIND(abi_test_clobber_lr);
+}
+#endif   // OPENSSL_PPC64LE && SUPPORTS_ABI_TEST
diff --git a/crypto/fipsmodule/modes/gcm_test.cc b/crypto/fipsmodule/modes/gcm_test.cc
index ca3d08a..031b06c 100644
--- a/crypto/fipsmodule/modes/gcm_test.cc
+++ b/crypto/fipsmodule/modes/gcm_test.cc
@@ -208,5 +208,15 @@
     }
   }
 #endif  // GHASH_ASM_ARM
+
+#if defined(GHASH_ASM_PPC64LE)
+  if (CRYPTO_is_PPC64LE_vcrypto_capable()) {
+    CHECK_ABI(gcm_init_p8, Htable, kH);
+    CHECK_ABI(gcm_gmult_p8, X, Htable);
+    for (size_t blocks : kBlockCounts) {
+      CHECK_ABI(gcm_ghash_p8, X, Htable, buf, 16 * blocks);
+    }
+  }
+#endif  // GHASH_ASM_PPC64LE
 }
 #endif  // SUPPORTS_ABI_TEST && !OPENSSL_NO_ASM
diff --git a/crypto/test/abi_test.h b/crypto/test/abi_test.h
index d65c7f8..ffe4479 100644
--- a/crypto/test/abi_test.h
+++ b/crypto/test/abi_test.h
@@ -179,7 +179,78 @@
   CALLER_STATE_REGISTER(uint64_t, x28)                               \
   CALLER_STATE_REGISTER(uint64_t, x29)
 
-#endif  // X86_64 || X86 || ARM || AARCH64
+#elif defined(OPENSSL_PPC64LE)
+
+// CRReg only compares the CR2-CR4 bits of a CR register.
+struct CRReg {
+  uint32_t masked() const { return value & 0x00fff000; }
+  bool operator==(CRReg r) const { return masked() == r.masked(); }
+  bool operator!=(CRReg r) const { return masked() != r.masked(); }
+  uint32_t value;
+};
+
+// References:
+// ELFv2: http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf
+//
+// Note vector and floating-point registers on POWER have two different names.
+// Originally, there were 32 floating-point registers and 32 vector registers,
+// labelled f0-f31 and v0-v31 respectively. Later, VSX (Vector Scalar Extension)
+// unified them into 64 registers vs0-vs63. f0-f31 map to the lower halves of
+// vs0-vs31. v0-v31 map to vs32-vs63. The ABI was defined in terms of pre-VSX
+// names, so we use those names here. In particular, f14-f31 are
+// callee-saved, but the upper halves of vs14-vs31 are not.
+#define LOOP_CALLER_STATE_REGISTERS()  \
+  CALLER_STATE_REGISTER(Reg128, v20)   \
+  CALLER_STATE_REGISTER(Reg128, v21)   \
+  CALLER_STATE_REGISTER(Reg128, v22)   \
+  CALLER_STATE_REGISTER(Reg128, v23)   \
+  CALLER_STATE_REGISTER(Reg128, v24)   \
+  CALLER_STATE_REGISTER(Reg128, v25)   \
+  CALLER_STATE_REGISTER(Reg128, v26)   \
+  CALLER_STATE_REGISTER(Reg128, v27)   \
+  CALLER_STATE_REGISTER(Reg128, v28)   \
+  CALLER_STATE_REGISTER(Reg128, v29)   \
+  CALLER_STATE_REGISTER(Reg128, v30)   \
+  CALLER_STATE_REGISTER(Reg128, v31)   \
+  CALLER_STATE_REGISTER(uint64_t, r14) \
+  CALLER_STATE_REGISTER(uint64_t, r15) \
+  CALLER_STATE_REGISTER(uint64_t, r16) \
+  CALLER_STATE_REGISTER(uint64_t, r17) \
+  CALLER_STATE_REGISTER(uint64_t, r18) \
+  CALLER_STATE_REGISTER(uint64_t, r19) \
+  CALLER_STATE_REGISTER(uint64_t, r20) \
+  CALLER_STATE_REGISTER(uint64_t, r21) \
+  CALLER_STATE_REGISTER(uint64_t, r22) \
+  CALLER_STATE_REGISTER(uint64_t, r23) \
+  CALLER_STATE_REGISTER(uint64_t, r24) \
+  CALLER_STATE_REGISTER(uint64_t, r25) \
+  CALLER_STATE_REGISTER(uint64_t, r26) \
+  CALLER_STATE_REGISTER(uint64_t, r27) \
+  CALLER_STATE_REGISTER(uint64_t, r28) \
+  CALLER_STATE_REGISTER(uint64_t, r29) \
+  CALLER_STATE_REGISTER(uint64_t, r30) \
+  CALLER_STATE_REGISTER(uint64_t, r31) \
+  CALLER_STATE_REGISTER(uint64_t, f14) \
+  CALLER_STATE_REGISTER(uint64_t, f15) \
+  CALLER_STATE_REGISTER(uint64_t, f16) \
+  CALLER_STATE_REGISTER(uint64_t, f17) \
+  CALLER_STATE_REGISTER(uint64_t, f18) \
+  CALLER_STATE_REGISTER(uint64_t, f19) \
+  CALLER_STATE_REGISTER(uint64_t, f20) \
+  CALLER_STATE_REGISTER(uint64_t, f21) \
+  CALLER_STATE_REGISTER(uint64_t, f22) \
+  CALLER_STATE_REGISTER(uint64_t, f23) \
+  CALLER_STATE_REGISTER(uint64_t, f24) \
+  CALLER_STATE_REGISTER(uint64_t, f25) \
+  CALLER_STATE_REGISTER(uint64_t, f26) \
+  CALLER_STATE_REGISTER(uint64_t, f27) \
+  CALLER_STATE_REGISTER(uint64_t, f28) \
+  CALLER_STATE_REGISTER(uint64_t, f29) \
+  CALLER_STATE_REGISTER(uint64_t, f30) \
+  CALLER_STATE_REGISTER(uint64_t, f31) \
+  CALLER_STATE_REGISTER(CRReg, cr)
+
+#endif  // X86_64 || X86 || ARM || AARCH64 || PPC64LE
 
 // Enable ABI testing if all of the following are true.
 //
@@ -210,24 +281,44 @@
 
 template <typename T>
 inline crypto_word_t ToWord(T t) {
-#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && \
-    !defined(OPENSSL_ARM) && !defined(OPENSSL_AARCH64)
-#error "Unknown architecture"
-#endif
+  // ABIs typically pass floats and structs differently from integers and
+  // pointers. We only need to support the latter.
+  static_assert(std::is_integral<T>::value || std::is_pointer<T>::value,
+                "parameter types must be integral or pointer types");
+  // We only support types which fit in registers.
   static_assert(sizeof(T) <= sizeof(crypto_word_t),
-                "T is larger than crypto_word_t");
-  static_assert(sizeof(T) >= 4, "types under four bytes are complicated");
+                "parameter types must be at most word-sized");
 
-  // ABIs are complex around arguments that are smaller than native words. For
-  // 32-bit architectures, the rules above imply we only have word-sized
-  // arguments. For 64-bit architectures, we still have assembly functions which
-  // take |int|.
+  // ABIs are complex around arguments that are smaller than native words.
+  // Parameters passed in memory are sometimes packed and sometimes padded to a
+  // word. When parameters are padded in memory or passed in a larger register,
+  // the unused bits may be undefined or sign- or zero-extended.
   //
-  // For aarch64, AAPCS64, section 5.4.2, clauses C.7 and C.14 says any
-  // remaining bits are unspecified. iOS64 contradicts this and says the callee
-  // extends arguments up to 32 bits, and only the upper 32 bits are
-  // unspecified. Rejecting parameters smaller than 32 bits avoids the
-  // divergence.
+  // We could simply cast to |crypto_word_t| everywhere but, on platforms where
+  // padding is undefined, we perturb the bits to test the function accounts for
+  // for this.
+#if defined(OPENSSL_32_BIT)
+  // We never pass parameters smaller than int, so require word-sized parameters
+  // on 32-bit architectures for simplicity.
+  static_assert(sizeof(T) == 4, "parameter types must be word-sized");
+  return (crypto_word_t)t;
+#elif defined(OPENSSL_PPC64LE)
+  // ELFv2, section 2.2.2.3 says the parameter save area sign- or zero-extends
+  // parameters passed in memory. Section 2.2.3 is unclear on how to handle
+  // register parameters, but section 2.2.2.3 additionally says that the memory
+  // copy of a parameter is identical to the register one.
+  return (crypto_word_t)t;
+#elif defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)
+  // AAPCS64, section 5.4.2, clauses C.7 and C.14 says any remaining bits in
+  // aarch are unspecified. iOS64 contradicts this and says the callee extends
+  // arguments up to 32 bits, and only the upper 32 bits are unspecified.
+  //
+  // On x86_64, Win64 leaves all unused bits unspecified. SysV also leaves
+  // unused bits in stack parameters unspecified, but it behaves like iOS64 for
+  // register parameters. This was determined via experimentation.
+  //
+  // We limit to 32-bit and 64-bit parameters, the subset where the above all
+  // align, and then test that functions tolerate arbitrary unused bits.
   //
   // TODO(davidben): Find authoritative citations for x86_64. For x86_64, I
   // observed the behavior of Clang, GCC, and MSVC. ABI rules here may be
@@ -241,27 +332,22 @@
   // 2. When compiling a small-argument-taking function, does the compiler make
   //    assumptions about unused bits of arguments?
   //
-  // MSVC for x86_64 is straightforward. It appears to tolerate and produce
-  // arbitrary values for unused bits, like AAPCS64.
-  //
-  // GCC and Clang for x86_64 are more complex. They match MSVC for stack
-  // parameters. However, for register parameters, they behave like iOS64 and,
-  // as callers, extend up to 32 bits, leaving the remainder arbitrary. When
-  // compiling a callee, Clang takes advantage of this conversion, but I was
-  // unable to make GCC do so.
-  //
-  // Note that, although the Win64 rules are sufficient to require our assembly
-  // be conservative, we wish for |CHECK_ABI| to support C-compiled functions,
-  // so it must enforce the correct rules for each platform.
-  //
-  // Fortunately, the |static_assert|s above cause all supported architectures
-  // to behave the same.
+  // MSVC was observed to tolerate and produce arbitrary values for unused bits,
+  // which is conclusive. GCC and Clang, targeting Linux, were similarly
+  // conclusive on stack parameters. Clang was also conclusive for register
+  // parameters. Callers only extended parameters up to 32 bits, and callees
+  // took advantage of the 32-bit extension. GCC only exhibited the callee
+  // behavior.
+  static_assert(sizeof(T) >= 4, "parameters must be at least 32 bits wide");
   crypto_word_t ret;
   // Filling extra bits with 0xaa will be vastly out of bounds for code
   // expecting either sign- or zero-extension. (0xaa is 0b10101010.)
   OPENSSL_memset(&ret, 0xaa, sizeof(ret));
   OPENSSL_memcpy(&ret, &t, sizeof(t));
   return ret;
+#else
+#error "unknown architecture"
+#endif
 }
 
 // CheckImpl runs |func| on |args|, recording ABI errors in |out|. If |unwind|
@@ -276,11 +362,9 @@
 template <typename R, typename... Args>
 inline crypto_word_t CheckImpl(Result *out, bool unwind, R (*func)(Args...),
                                typename DeductionGuard<Args>::Type... args) {
-  // We only support up to 8 arguments. This ensures all arguments on aarch64
-  // are passed in registers and avoids the iOS descrepancy around packing small
-  // arguments on the stack.
-  //
-  // https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
+  // We only support up to 8 arguments, so all arguments on aarch64 and ppc64le
+  // are passed in registers. This is simpler and avoids the iOS discrepancy
+  // around packing small arguments on the stack. (See the iOS64 reference.)
   static_assert(sizeof...(args) <= 8,
                 "too many arguments for abi_test_trampoline");
 
diff --git a/crypto/test/asm/trampoline-ppc.pl b/crypto/test/asm/trampoline-ppc.pl
new file mode 100755
index 0000000..a8d7c3f
--- /dev/null
+++ b/crypto/test/asm/trampoline-ppc.pl
@@ -0,0 +1,262 @@
+#!/usr/bin/env perl
+# Copyright (c) 2019, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# This file defines helper functions for crypto/test/abi_test.h on ppc64le. See
+# that header for details on how to use this.
+#
+# For convenience, this file is linked into libcrypto, where consuming builds
+# already support architecture-specific sources. The static linker should drop
+# this code in non-test binaries. This includes a shared library build of
+# libcrypto, provided --gc-sections or equivalent is used.
+#
+# References:
+#
+# ELFv2: http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf
+
+use strict;
+
+my $flavour = shift;
+my $output  = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/;
+my $dir = $1;
+my $xlate;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
+*STDOUT = *OUT;
+
+unless ($flavour =~ /linux.*64le/) {
+    die "This file only supports the ELFv2 ABI, used by ppc64le";
+}
+
+my $code = "";
+
+sub load_or_store_regs {
+  # $op is "l" or "st".
+  my ($op, $base_reg, $base_offset) = @_;
+  # Vector registers.
+  foreach (20..31) {
+    my $offset = $base_offset + ($_ - 20) * 16;
+    # Vector registers only support indexed register addressing.
+    $code .= "\tli\tr11, $offset\n";
+    $code .= "\t${op}vx\tv$_, r11, $base_reg\n";
+  }
+  # Save general registers.
+  foreach (14..31) {
+    my $offset = $base_offset + 192 + ($_ - 14) * 8;
+    $code .= "\t${op}d\tr$_, $offset($base_reg)\n";
+  }
+  # Save floating point registers.
+  foreach (14..31) {
+    my $offset = $base_offset + 336 + ($_ - 14) * 8;
+    $code .= "\t${op}fd\tf$_, $offset($base_reg)\n";
+  }
+}
+
+sub load_regs {
+  my ($base_reg, $base_offset) = @_;
+  load_or_store_regs("l", $base_reg, $base_offset);
+}
+
+sub store_regs {
+  my ($base_reg, $base_offset) = @_;
+  load_or_store_regs("st", $base_reg, $base_offset);
+}
+
+my ($func, $state, $argv, $argc) = ("r3", "r4", "r5", "r6");
+$code .= <<____;
+.machine	"any"
+.text
+
+# abi_test_trampoline loads callee-saved registers from |state|, calls |func|
+# with |argv|, then saves the callee-saved registers into |state|. It returns
+# the result of |func|. The |unwind| argument is unused.
+# uint64_t abi_test_trampoline(void (*func)(...), CallerState *state,
+#                              const uint64_t *argv, size_t argc,
+#                              uint64_t unwind);
+.globl	abi_test_trampoline
+.align	5
+abi_test_trampoline:
+	# LR is saved into the caller's stack frame.
+	mflr	r0
+	std	r0, 16(r1)
+
+	# Allocate 66*8 = 528 bytes of stack frame. From the top of the stack
+	# to the bottom, the stack frame is:
+	#
+	#     0(r1) - Back chain pointer
+	#     8(r1) - CR save area
+	#    16(r1) - LR save area (for |func|)
+	#    24(r1) - TOC pointer save area
+	#    32(r1) - Saved copy of |state|
+	#    40(r1) - Padding
+	#    48(r1) - Vector register save area (v20-v31, 12 registers)
+	#   240(r1) - General register save area (r14-r31, 18 registers)
+	#   384(r1) - Floating point register save area (f14-f31, 18 registers)
+	#
+	# Note the layouts of the register save areas and CallerState match.
+	#
+	# In the ELFv2 ABI, the parameter save area is optional if the function
+	# is non-variadic and all parameters fit in registers. We only support
+	# such functions, so we omit it to test that |func| does not rely on it.
+	stdu	r1, -528(r1)
+
+	mfcr	r0
+	std	r0, 8(r1)	# Save CR
+	std	r2, 24(r1)	# Save TOC
+	std	$state, 32(r1)	# Save |state|
+____
+# Save registers to the stack.
+store_regs("r1", 48);
+# Load registers from the caller.
+load_regs($state, 0);
+$code .= <<____;
+	# Load CR from |state|.
+	ld	r0, 480($state)
+	mtcr	r0
+
+	# Move parameters into temporary registers so they are not clobbered.
+	addi	r11, $argv, -8	# Adjust for ldu below
+	mr	r12, $func
+
+	# Load parameters into registers.
+	cmpdi	$argc, 0
+	beq	.Largs_done
+	mtctr	$argc
+	ldu	r3, 8(r11)
+	bdz	.Largs_done
+	ldu	r4, 8(r11)
+	bdz	.Largs_done
+	ldu	r5, 8(r11)
+	bdz	.Largs_done
+	ldu	r6, 8(r11)
+	bdz	.Largs_done
+	ldu	r7, 8(r11)
+	bdz	.Largs_done
+	ldu	r8, 8(r11)
+	bdz	.Largs_done
+	ldu	r9, 8(r11)
+	bdz	.Largs_done
+	ldu	r10, 8(r11)
+
+.Largs_done:
+	li	r2, 0		# Clear TOC to test |func|'s global entry point
+	mtctr	r12
+	bctrl
+	ld	r2, 24(r1)	# Restore TOC
+
+	ld	$state, 32(r1)	# Reload |state|
+____
+# Output resulting registers to the caller.
+store_regs($state, 0);
+# Restore registers from the stack.
+load_regs("r1", 48);
+$code .= <<____;
+	mfcr	r0
+	std	r0, 480($state)	# Output CR to caller
+	ld	r0, 8(r1)
+	mtcrf	0b00111000, r0	# Restore CR2-CR4
+	addi	r1, r1, 528
+	ld	r0, 16(r1)	# Restore LR
+	mtlr	r0
+	blr
+.size	abi_test_trampoline,.-abi_test_trampoline
+____
+
+# abi_test_clobber_* clobbers the corresponding register. These are used to test
+# the ABI-testing framework.
+foreach (0..31) {
+  # r1 is the stack pointer. r13 is the thread pointer.
+  next if ($_ == 1 || $_ == 13);
+  $code .= <<____;
+.globl	abi_test_clobber_r$_
+.align	5
+abi_test_clobber_r$_:
+	li	r$_, 0
+	blr
+.size	abi_test_clobber_r$_,.-abi_test_clobber_r$_
+____
+}
+
+foreach (0..31) {
+  $code .= <<____;
+.globl	abi_test_clobber_f$_
+.align	4
+abi_test_clobber_f$_:
+	li	r0, 0
+	# Use the red zone.
+	std	r0, -8(r1)
+	lfd	f$_, -8(r1)
+	blr
+.size	abi_test_clobber_f$_,.-abi_test_clobber_f$_
+____
+}
+
+foreach (0..31) {
+  $code .= <<____;
+.globl	abi_test_clobber_v$_
+.align	4
+abi_test_clobber_v$_:
+	vxor	v$_, v$_, v$_
+	blr
+.size	abi_test_clobber_v$_,.-abi_test_clobber_v$_
+____
+}
+
+foreach (0..7) {
+  # PPC orders CR fields in big-endian, so the mask is reversed from what one
+  # would expect.
+  my $mask = 1 << (7 - $_);
+  $code .= <<____;
+.globl	abi_test_clobber_cr$_
+.align	4
+abi_test_clobber_cr$_:
+	# Flip the bits on cr$_ rather than setting to zero. With a four-bit
+	# register, zeroing it will do nothing 1 in 16 times.
+	mfcr	r0
+	not	r0, r0
+	mtcrf	$mask, r0
+	blr
+.size	abi_test_clobber_cr$_,.-abi_test_clobber_cr$_
+____
+}
+
+$code .= <<____;
+.globl	abi_test_clobber_ctr
+.align	4
+abi_test_clobber_ctr:
+	li	r0, 0
+	mtctr	r0
+	blr
+.size	abi_test_clobber_ctr,.-abi_test_clobber_ctr
+
+.globl	abi_test_clobber_lr
+.align	4
+abi_test_clobber_lr:
+	mflr	r0
+	mtctr	r0
+	li	r0, 0
+	mtlr	r0
+	bctr
+.size	abi_test_clobber_lr,.-abi_test_clobber_lr
+
+____
+
+print $code;
+close STDOUT or die "error closing STDOUT";