all: $(TEST_GEN_PROGS) $(TEST_PROGS_EXTENDED)
 
-fpsimd-test: fpsimd-test.o
+fpsimd-test: fpsimd-test.o asm-utils.o
        $(CC) -nostdlib $^ -o $@
 rdvl-sve: rdvl-sve.o rdvl.o
 sve-ptrace: sve-ptrace.o
 sve-probe-vls: sve-probe-vls.o rdvl.o
-sve-test: sve-test.o
+sve-test: sve-test.o asm-utils.o
        $(CC) -nostdlib $^ -o $@
 vec-syscfg: vec-syscfg.o rdvl.o
 vlset: vlset.o
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2015-2021 ARM Limited.
+// Original author: Dave Martin <Dave.Martin@arm.com>
+//
+// Utility functions for assembly code.
+
+#include <asm/unistd.h>
+#include "assembler.h"
+
+// Print a single character x0 to stdout
+// Clobbers x0-x2,x8
+function putc
+       str     x0, [sp, #-16]!
+
+       mov     x0, #1                  // STDOUT_FILENO
+       mov     x1, sp
+       mov     x2, #1
+       mov     x8, #__NR_write
+       svc     #0
+
+       add     sp, sp, #16
+       ret
+endfunction
+.globl putc
+       
+// Print a NUL-terminated string starting at address x0 to stdout
+// Clobbers x0-x3,x8
+function puts
+       mov     x1, x0
+
+       mov     x2, #0
+0:     ldrb    w3, [x0], #1
+       cbz     w3, 1f
+       add     x2, x2, #1
+       b       0b
+
+1:     mov     w0, #1                  // STDOUT_FILENO
+       mov     x8, #__NR_write
+       svc     #0
+
+       ret
+endfunction
+.globl puts
+
+// Print an unsigned decimal number x0 to stdout
+// Clobbers x0-x4,x8
+function putdec
+       mov     x1, sp
+       str     x30, [sp, #-32]!        // Result can't be > 20 digits
+
+       mov     x2, #0
+       strb    w2, [x1, #-1]!          // Write the NUL terminator
+
+       mov     x2, #10
+0:     udiv    x3, x0, x2              // div-mod loop to generate the digits
+       msub    x0, x3, x2, x0
+       add     w0, w0, #'0'
+       strb    w0, [x1, #-1]!
+       mov     x0, x3
+       cbnz    x3, 0b
+
+       ldrb    w0, [x1]
+       cbnz    w0, 1f
+       mov     w0, #'0'                // Print "0" for 0, not ""
+       strb    w0, [x1, #-1]!
+
+1:     mov     x0, x1
+       bl      puts
+
+       ldr     x30, [sp], #32
+       ret
+endfunction
+.globl putdec
+
+// Print an unsigned decimal number x0 to stdout, followed by a newline
+// Clobbers x0-x5,x8
+function putdecn
+       mov     x5, x30
+
+       bl      putdec
+       mov     x0, #'\n'
+       bl      putc
+
+       ret     x5
+endfunction
+.globl putdecn
+
+// Clobbers x0-x3,x8
+function puthexb
+       str     x30, [sp, #-0x10]!
+
+       mov     w3, w0
+       lsr     w0, w0, #4
+       bl      puthexnibble
+       mov     w0, w3
+
+       ldr     x30, [sp], #0x10
+       // fall through to puthexnibble
+endfunction
+.globl puthexb
+
+// Clobbers x0-x2,x8
+function puthexnibble
+       and     w0, w0, #0xf
+       cmp     w0, #10
+       blo     1f
+       add     w0, w0, #'a' - ('9' + 1)
+1:     add     w0, w0, #'0'
+       b       putc
+endfunction
+.globl puthexnibble
+
+// x0=data in, x1=size in, clobbers x0-x5,x8
+function dumphex
+       str     x30, [sp, #-0x10]!
+
+       mov     x4, x0
+       mov     x5, x1
+
+0:     subs    x5, x5, #1
+       b.lo    1f
+       ldrb    w0, [x4], #1
+       bl      puthexb
+       b       0b
+
+1:     ldr     x30, [sp], #0x10
+       ret
+endfunction
+.globl dumphex
+
+       // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
+// Clobbers x0-x3
+function memcpy
+       cmp     x2, #0
+       b.eq    1f
+0:     ldrb    w3, [x1], #1
+       strb    w3, [x0], #1
+       subs    x2, x2, #1
+       b.ne    0b
+1:     ret
+endfunction
+.globl memcpy
+
+// Fill x1 bytes starting at x0 with 0xae (for canary purposes)
+// Clobbers x1, x2.
+function memfill_ae
+       mov     w2, #0xae
+       b       memfill
+endfunction
+.globl memfill_ae
+       
+// Fill x1 bytes starting at x0 with 0.
+// Clobbers x1, x2.
+function memclr
+       mov     w2, #0
+endfunction
+.globl memclr
+       // fall through to memfill
+
+// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
+// Clobbers x1
+function memfill
+       cmp     x1, #0
+       b.eq    1f
+
+0:     strb    w2, [x0], #1
+       subs    x1, x1, #1
+       b.ne    0b
+
+1:     ret
+endfunction
+.globl memfill
 
        .purgem \name\()_entry
 .endm
 
+// Utility macro to print a literal string
+// Clobbers x0-x4,x8
+.macro puts string
+       .pushsection .rodata.str1.1, "aMS", 1
+.L__puts_literal\@: .string "\string"
+       .popsection
+
+       ldr     x0, =.L__puts_literal\@
+       bl      puts
+.endm
+
 #endif /* ! ASSEMBLER_H */
 
 define_accessor setv, NVR, _vldr
 define_accessor getv, NVR, _vstr
 
-// Print a single character x0 to stdout
-// Clobbers x0-x2,x8
-function putc
-       str     x0, [sp, #-16]!
-
-       mov     x0, #1                  // STDOUT_FILENO
-       mov     x1, sp
-       mov     x2, #1
-       mov     x8, #__NR_write
-       svc     #0
-
-       add     sp, sp, #16
-       ret
-endfunction
-
-// Print a NUL-terminated string starting at address x0 to stdout
-// Clobbers x0-x3,x8
-function puts
-       mov     x1, x0
-
-       mov     x2, #0
-0:     ldrb    w3, [x0], #1
-       cbz     w3, 1f
-       add     x2, x2, #1
-       b       0b
-
-1:     mov     w0, #1                  // STDOUT_FILENO
-       mov     x8, #__NR_write
-       svc     #0
-
-       ret
-endfunction
-
-// Utility macro to print a literal string
-// Clobbers x0-x4,x8
-.macro puts string
-       .pushsection .rodata.str1.1, "aMS", 1
-.L__puts_literal\@: .string "\string"
-       .popsection
-
-       ldr     x0, =.L__puts_literal\@
-       bl      puts
-.endm
-
-// Print an unsigned decimal number x0 to stdout
-// Clobbers x0-x4,x8
-function putdec
-       mov     x1, sp
-       str     x30, [sp, #-32]!        // Result can't be > 20 digits
-
-       mov     x2, #0
-       strb    w2, [x1, #-1]!          // Write the NUL terminator
-
-       mov     x2, #10
-0:     udiv    x3, x0, x2              // div-mod loop to generate the digits
-       msub    x0, x3, x2, x0
-       add     w0, w0, #'0'
-       strb    w0, [x1, #-1]!
-       mov     x0, x3
-       cbnz    x3, 0b
-
-       ldrb    w0, [x1]
-       cbnz    w0, 1f
-       mov     w0, #'0'                // Print "0" for 0, not ""
-       strb    w0, [x1, #-1]!
-
-1:     mov     x0, x1
-       bl      puts
-
-       ldr     x30, [sp], #32
-       ret
-endfunction
-
-// Print an unsigned decimal number x0 to stdout, followed by a newline
-// Clobbers x0-x5,x8
-function putdecn
-       mov     x5, x30
-
-       bl      putdec
-       mov     x0, #'\n'
-       bl      putc
-
-       ret     x5
-endfunction
-
-
-// Clobbers x0-x3,x8
-function puthexb
-       str     x30, [sp, #-0x10]!
-
-       mov     w3, w0
-       lsr     w0, w0, #4
-       bl      puthexnibble
-       mov     w0, w3
-
-       ldr     x30, [sp], #0x10
-       // fall through to puthexnibble
-endfunction
-// Clobbers x0-x2,x8
-function puthexnibble
-       and     w0, w0, #0xf
-       cmp     w0, #10
-       blo     1f
-       add     w0, w0, #'a' - ('9' + 1)
-1:     add     w0, w0, #'0'
-       b       putc
-endfunction
-
-// x0=data in, x1=size in, clobbers x0-x5,x8
-function dumphex
-       str     x30, [sp, #-0x10]!
-
-       mov     x4, x0
-       mov     x5, x1
-
-0:     subs    x5, x5, #1
-       b.lo    1f
-       ldrb    w0, [x4], #1
-       bl      puthexb
-       b       0b
-
-1:     ldr     x30, [sp], #0x10
-       ret
-endfunction
-
 // Declare some storate space to shadow the SVE register contents:
 .pushsection .text
 .data
        .space  MAXVL_B
 .popsection
 
-// Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
-// Clobbers x0-x3
-function memcpy
-       cmp     x2, #0
-       b.eq    1f
-0:     ldrb    w3, [x1], #1
-       strb    w3, [x0], #1
-       subs    x2, x2, #1
-       b.ne    0b
-1:     ret
-endfunction
-
 // Generate a test pattern for storage in SVE registers
 // x0: pid     (16 bits)
 // x1: register number (6 bits)
        ret     x4
 endfunction
 
-// Fill x1 bytes starting at x0 with 0xae (for canary purposes)
-// Clobbers x1, x2.
-function memfill_ae
-       mov     w2, #0xae
-       b       memfill
-endfunction
-
-// Fill x1 bytes starting at x0 with 0.
-// Clobbers x1, x2.
-function memclr
-       mov     w2, #0
-endfunction
-       // fall through to memfill
-
-// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
-// Clobbers x1
-function memfill
-       cmp     x1, #0
-       b.eq    1f
-
-0:     strb    w2, [x0], #1
-       subs    x1, x1, #1
-       b.ne    0b
-
-1:     ret
-endfunction
-
 // Trivial memory compare: compare x2 bytes starting at address x0 with
 // bytes starting at address x1.
 // Returns only if all bytes match; otherwise, the program is aborted.
 
 define_accessor setp, NPR, _sve_ldr_p
 define_accessor getp, NPR, _sve_str_p
 
-// Print a single character x0 to stdout
-// Clobbers x0-x2,x8
-function putc
-       str     x0, [sp, #-16]!
-
-       mov     x0, #1                  // STDOUT_FILENO
-       mov     x1, sp
-       mov     x2, #1
-       mov     x8, #__NR_write
-       svc     #0
-
-       add     sp, sp, #16
-       ret
-endfunction
-
-// Print a NUL-terminated string starting at address x0 to stdout
-// Clobbers x0-x3,x8
-function puts
-       mov     x1, x0
-
-       mov     x2, #0
-0:     ldrb    w3, [x0], #1
-       cbz     w3, 1f
-       add     x2, x2, #1
-       b       0b
-
-1:     mov     w0, #1                  // STDOUT_FILENO
-       mov     x8, #__NR_write
-       svc     #0
-
-       ret
-endfunction
-
-// Utility macro to print a literal string
-// Clobbers x0-x4,x8
-.macro puts string
-       .pushsection .rodata.str1.1, "aMS", 1
-.L__puts_literal\@: .string "\string"
-       .popsection
-
-       ldr     x0, =.L__puts_literal\@
-       bl      puts
-.endm
-
-// Print an unsigned decimal number x0 to stdout
-// Clobbers x0-x4,x8
-function putdec
-       mov     x1, sp
-       str     x30, [sp, #-32]!        // Result can't be > 20 digits
-
-       mov     x2, #0
-       strb    w2, [x1, #-1]!          // Write the NUL terminator
-
-       mov     x2, #10
-0:     udiv    x3, x0, x2              // div-mod loop to generate the digits
-       msub    x0, x3, x2, x0
-       add     w0, w0, #'0'
-       strb    w0, [x1, #-1]!
-       mov     x0, x3
-       cbnz    x3, 0b
-
-       ldrb    w0, [x1]
-       cbnz    w0, 1f
-       mov     w0, #'0'                // Print "0" for 0, not ""
-       strb    w0, [x1, #-1]!
-
-1:     mov     x0, x1
-       bl      puts
-
-       ldr     x30, [sp], #32
-       ret
-endfunction
-
-// Print an unsigned decimal number x0 to stdout, followed by a newline
-// Clobbers x0-x5,x8
-function putdecn
-       mov     x5, x30
-
-       bl      putdec
-       mov     x0, #'\n'
-       bl      putc
-
-       ret     x5
-endfunction
-
-// Clobbers x0-x3,x8
-function puthexb
-       str     x30, [sp, #-0x10]!
-
-       mov     w3, w0
-       lsr     w0, w0, #4
-       bl      puthexnibble
-       mov     w0, w3
-
-       ldr     x30, [sp], #0x10
-       // fall through to puthexnibble
-endfunction
-// Clobbers x0-x2,x8
-function puthexnibble
-       and     w0, w0, #0xf
-       cmp     w0, #10
-       blo     1f
-       add     w0, w0, #'a' - ('9' + 1)
-1:     add     w0, w0, #'0'
-       b       putc
-endfunction
-
-// x0=data in, x1=size in, clobbers x0-x5,x8
-function dumphex
-       str     x30, [sp, #-0x10]!
-
-       mov     x4, x0
-       mov     x5, x1
-
-0:     subs    x5, x5, #1
-       b.lo    1f
-       ldrb    w0, [x4], #1
-       bl      puthexb
-       b       0b
-
-1:     ldr     x30, [sp], #0x10
-       ret
-endfunction
-
 // Declare some storate space to shadow the SVE register contents:
 .pushsection .text
 .data
        .space  MAXVL_B
 .popsection
 
-// Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
-// Clobbers x0-x3
-function memcpy
-       cmp     x2, #0
-       b.eq    1f
-0:     ldrb    w3, [x1], #1
-       strb    w3, [x0], #1
-       subs    x2, x2, #1
-       b.ne    0b
-1:     ret
-endfunction
-
 // Generate a test pattern for storage in SVE registers
 // x0: pid     (16 bits)
 // x1: register number (6 bits)
        ret     x4
 endfunction
 
-// Fill x1 bytes starting at x0 with 0xae (for canary purposes)
-// Clobbers x1, x2.
-function memfill_ae
-       mov     w2, #0xae
-       b       memfill
-endfunction
-
-// Fill x1 bytes starting at x0 with 0.
-// Clobbers x1, x2.
-function memclr
-       mov     w2, #0
-endfunction
-       // fall through to memfill
-
-// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
-// Clobbers x1
-function memfill
-       cmp     x1, #0
-       b.eq    1f
-
-0:     strb    w2, [x0], #1
-       subs    x1, x1, #1
-       b.ne    0b
-
-1:     ret
-endfunction
-
 // Trivial memory compare: compare x2 bytes starting at address x0 with
 // bytes starting at address x1.
 // Returns only if all bytes match; otherwise, the program is aborted.