1*260ea4baSMark Brown// SPDX-License-Identifier: GPL-2.0-only 2*260ea4baSMark Brown// Copyright (C) 2015-2021 ARM Limited. 3*260ea4baSMark Brown// Original author: Dave Martin <Dave.Martin@arm.com> 4*260ea4baSMark Brown// 5*260ea4baSMark Brown// Utility functions for assembly code. 6*260ea4baSMark Brown 7*260ea4baSMark Brown#include <asm/unistd.h> 8*260ea4baSMark Brown#include "assembler.h" 9*260ea4baSMark Brown 10*260ea4baSMark Brown// Print a single character x0 to stdout 11*260ea4baSMark Brown// Clobbers x0-x2,x8 12*260ea4baSMark Brownfunction putc 13*260ea4baSMark Brown str x0, [sp, #-16]! 14*260ea4baSMark Brown 15*260ea4baSMark Brown mov x0, #1 // STDOUT_FILENO 16*260ea4baSMark Brown mov x1, sp 17*260ea4baSMark Brown mov x2, #1 18*260ea4baSMark Brown mov x8, #__NR_write 19*260ea4baSMark Brown svc #0 20*260ea4baSMark Brown 21*260ea4baSMark Brown add sp, sp, #16 22*260ea4baSMark Brown ret 23*260ea4baSMark Brownendfunction 24*260ea4baSMark Brown.globl putc 25*260ea4baSMark Brown 26*260ea4baSMark Brown// Print a NUL-terminated string starting at address x0 to stdout 27*260ea4baSMark Brown// Clobbers x0-x3,x8 28*260ea4baSMark Brownfunction puts 29*260ea4baSMark Brown mov x1, x0 30*260ea4baSMark Brown 31*260ea4baSMark Brown mov x2, #0 32*260ea4baSMark Brown0: ldrb w3, [x0], #1 33*260ea4baSMark Brown cbz w3, 1f 34*260ea4baSMark Brown add x2, x2, #1 35*260ea4baSMark Brown b 0b 36*260ea4baSMark Brown 37*260ea4baSMark Brown1: mov w0, #1 // STDOUT_FILENO 38*260ea4baSMark Brown mov x8, #__NR_write 39*260ea4baSMark Brown svc #0 40*260ea4baSMark Brown 41*260ea4baSMark Brown ret 42*260ea4baSMark Brownendfunction 43*260ea4baSMark Brown.globl puts 44*260ea4baSMark Brown 45*260ea4baSMark Brown// Print an unsigned decimal number x0 to stdout 46*260ea4baSMark Brown// Clobbers x0-x4,x8 47*260ea4baSMark Brownfunction putdec 48*260ea4baSMark Brown mov x1, sp 49*260ea4baSMark Brown str x30, [sp, #-32]! // Result can't be > 20 digits 50*260ea4baSMark Brown 51*260ea4baSMark Brown mov x2, #0 52*260ea4baSMark Brown strb w2, [x1, #-1]! // Write the NUL terminator 53*260ea4baSMark Brown 54*260ea4baSMark Brown mov x2, #10 55*260ea4baSMark Brown0: udiv x3, x0, x2 // div-mod loop to generate the digits 56*260ea4baSMark Brown msub x0, x3, x2, x0 57*260ea4baSMark Brown add w0, w0, #'0' 58*260ea4baSMark Brown strb w0, [x1, #-1]! 59*260ea4baSMark Brown mov x0, x3 60*260ea4baSMark Brown cbnz x3, 0b 61*260ea4baSMark Brown 62*260ea4baSMark Brown ldrb w0, [x1] 63*260ea4baSMark Brown cbnz w0, 1f 64*260ea4baSMark Brown mov w0, #'0' // Print "0" for 0, not "" 65*260ea4baSMark Brown strb w0, [x1, #-1]! 66*260ea4baSMark Brown 67*260ea4baSMark Brown1: mov x0, x1 68*260ea4baSMark Brown bl puts 69*260ea4baSMark Brown 70*260ea4baSMark Brown ldr x30, [sp], #32 71*260ea4baSMark Brown ret 72*260ea4baSMark Brownendfunction 73*260ea4baSMark Brown.globl putdec 74*260ea4baSMark Brown 75*260ea4baSMark Brown// Print an unsigned decimal number x0 to stdout, followed by a newline 76*260ea4baSMark Brown// Clobbers x0-x5,x8 77*260ea4baSMark Brownfunction putdecn 78*260ea4baSMark Brown mov x5, x30 79*260ea4baSMark Brown 80*260ea4baSMark Brown bl putdec 81*260ea4baSMark Brown mov x0, #'\n' 82*260ea4baSMark Brown bl putc 83*260ea4baSMark Brown 84*260ea4baSMark Brown ret x5 85*260ea4baSMark Brownendfunction 86*260ea4baSMark Brown.globl putdecn 87*260ea4baSMark Brown 88*260ea4baSMark Brown// Clobbers x0-x3,x8 89*260ea4baSMark Brownfunction puthexb 90*260ea4baSMark Brown str x30, [sp, #-0x10]! 91*260ea4baSMark Brown 92*260ea4baSMark Brown mov w3, w0 93*260ea4baSMark Brown lsr w0, w0, #4 94*260ea4baSMark Brown bl puthexnibble 95*260ea4baSMark Brown mov w0, w3 96*260ea4baSMark Brown 97*260ea4baSMark Brown ldr x30, [sp], #0x10 98*260ea4baSMark Brown // fall through to puthexnibble 99*260ea4baSMark Brownendfunction 100*260ea4baSMark Brown.globl puthexb 101*260ea4baSMark Brown 102*260ea4baSMark Brown// Clobbers x0-x2,x8 103*260ea4baSMark Brownfunction puthexnibble 104*260ea4baSMark Brown and w0, w0, #0xf 105*260ea4baSMark Brown cmp w0, #10 106*260ea4baSMark Brown blo 1f 107*260ea4baSMark Brown add w0, w0, #'a' - ('9' + 1) 108*260ea4baSMark Brown1: add w0, w0, #'0' 109*260ea4baSMark Brown b putc 110*260ea4baSMark Brownendfunction 111*260ea4baSMark Brown.globl puthexnibble 112*260ea4baSMark Brown 113*260ea4baSMark Brown// x0=data in, x1=size in, clobbers x0-x5,x8 114*260ea4baSMark Brownfunction dumphex 115*260ea4baSMark Brown str x30, [sp, #-0x10]! 116*260ea4baSMark Brown 117*260ea4baSMark Brown mov x4, x0 118*260ea4baSMark Brown mov x5, x1 119*260ea4baSMark Brown 120*260ea4baSMark Brown0: subs x5, x5, #1 121*260ea4baSMark Brown b.lo 1f 122*260ea4baSMark Brown ldrb w0, [x4], #1 123*260ea4baSMark Brown bl puthexb 124*260ea4baSMark Brown b 0b 125*260ea4baSMark Brown 126*260ea4baSMark Brown1: ldr x30, [sp], #0x10 127*260ea4baSMark Brown ret 128*260ea4baSMark Brownendfunction 129*260ea4baSMark Brown.globl dumphex 130*260ea4baSMark Brown 131*260ea4baSMark Brown // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0. 132*260ea4baSMark Brown// Clobbers x0-x3 133*260ea4baSMark Brownfunction memcpy 134*260ea4baSMark Brown cmp x2, #0 135*260ea4baSMark Brown b.eq 1f 136*260ea4baSMark Brown0: ldrb w3, [x1], #1 137*260ea4baSMark Brown strb w3, [x0], #1 138*260ea4baSMark Brown subs x2, x2, #1 139*260ea4baSMark Brown b.ne 0b 140*260ea4baSMark Brown1: ret 141*260ea4baSMark Brownendfunction 142*260ea4baSMark Brown.globl memcpy 143*260ea4baSMark Brown 144*260ea4baSMark Brown// Fill x1 bytes starting at x0 with 0xae (for canary purposes) 145*260ea4baSMark Brown// Clobbers x1, x2. 146*260ea4baSMark Brownfunction memfill_ae 147*260ea4baSMark Brown mov w2, #0xae 148*260ea4baSMark Brown b memfill 149*260ea4baSMark Brownendfunction 150*260ea4baSMark Brown.globl memfill_ae 151*260ea4baSMark Brown 152*260ea4baSMark Brown// Fill x1 bytes starting at x0 with 0. 153*260ea4baSMark Brown// Clobbers x1, x2. 154*260ea4baSMark Brownfunction memclr 155*260ea4baSMark Brown mov w2, #0 156*260ea4baSMark Brownendfunction 157*260ea4baSMark Brown.globl memclr 158*260ea4baSMark Brown // fall through to memfill 159*260ea4baSMark Brown 160*260ea4baSMark Brown// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2 161*260ea4baSMark Brown// Clobbers x1 162*260ea4baSMark Brownfunction memfill 163*260ea4baSMark Brown cmp x1, #0 164*260ea4baSMark Brown b.eq 1f 165*260ea4baSMark Brown 166*260ea4baSMark Brown0: strb w2, [x0], #1 167*260ea4baSMark Brown subs x1, x1, #1 168*260ea4baSMark Brown b.ne 0b 169*260ea4baSMark Brown 170*260ea4baSMark Brown1: ret 171*260ea4baSMark Brownendfunction 172*260ea4baSMark Brown.globl memfill 173