--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * test helper assembly functions
+ *
+ * Copyright (C) 2016 Simon Guo, IBM Corporation.
+ * Copyright 2022 Michael Ellerman, IBM Corporation.
+ */
+#include "basic_asm.h"
+
+#define GPR_SIZE       __SIZEOF_LONG__
+#define FIRST_GPR      14
+#define NUM_GPRS       (32 - FIRST_GPR)
+#define STACK_SIZE     (NUM_GPRS * GPR_SIZE)
+
+// gpr_child_loop(int *read_flag, int *write_flag,
+//               unsigned long *gpr_buf, double *fpr_buf);
+FUNC_START(gpr_child_loop)
+       // r3 = read_flag
+       // r4 = write_flag
+       // r5 = gpr_buf
+       // r6 = fpr_buf
+       PUSH_BASIC_STACK(STACK_SIZE)
+
+       // Save non-volatile GPRs
+       OP_REGS PPC_STL, GPR_SIZE, FIRST_GPR, 31, %r1, STACK_FRAME_LOCAL(0, 0), FIRST_GPR
+
+       // Load GPRs with expected values
+       OP_REGS PPC_LL, GPR_SIZE, FIRST_GPR, 31, r5, 0, FIRST_GPR
+
+       // Load FPRs with expected values
+       OP_REGS lfd, 8, 0, 31, r6
+
+       // Signal to parent that we're ready
+       li      r0, 1
+       stw     r0, 0(r4)
+
+       // Wait for parent to finish
+1:     lwz     r0, 0(r3)
+       cmpwi   r0, 0
+       beq     1b      // Loop while flag is zero
+
+       // Save GPRs back to caller buffer
+       OP_REGS PPC_STL, GPR_SIZE, FIRST_GPR, 31, r5, 0, FIRST_GPR
+
+       // Save FPRs
+       OP_REGS stfd, 8, 0, 31, r6
+
+       // Reload non-volatile GPRs
+       OP_REGS PPC_LL, GPR_SIZE, FIRST_GPR, 31, %r1, STACK_FRAME_LOCAL(0, 0), FIRST_GPR
+
+       POP_BASIC_STACK(STACK_SIZE)
+       blr
 
 double b = FPR_2;
 double c = FPR_3;
 
+extern void gpr_child_loop(int *read_flag, int *write_flag,
+                          unsigned long *gpr_buf, double *fpr_buf);
+
 void gpr(void)
 {
-       unsigned long gpr_buf[18];
+       unsigned long gpr_buf[32];
        double fpr_buf[32];
+       int i;
 
        cptr = (int *)shmat(shm_id, NULL, 0);
+       memset(gpr_buf, 0, sizeof(gpr_buf));
+       memset(fpr_buf, 0, sizeof(fpr_buf));
 
-       asm __volatile__(
-               ASM_LOAD_GPR_IMMED(gpr_1)
-               ASM_LOAD_FPR(flt_1)
-               :
-               : [gpr_1]"i"(GPR_1), [flt_1] "b" (&a)
-               : "memory", "r6", "r7", "r8", "r9", "r10",
-               "r11", "r12", "r13", "r14", "r15", "r16", "r17",
-               "r18", "r19", "r20", "r21", "r22", "r23", "r24",
-               "r25", "r26", "r27", "r28", "r29", "r30", "r31"
-               );
-
-       cptr[1] = 1;
+       for (i = 0; i < 32; i++) {
+               gpr_buf[i] = GPR_1;
+               fpr_buf[i] = a;
+       }
 
-       while (!cptr[0])
-               asm volatile("" : : : "memory");
+       gpr_child_loop(&cptr[0], &cptr[1], gpr_buf, fpr_buf);
 
        shmdt((void *)cptr);
-       store_gpr(gpr_buf);
-       store_fpr(fpr_buf);
 
        if (validate_gpr(gpr_buf, GPR_3))
                exit(1);