0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright (C) 2015-2021 ARM Limited.
0003 // Original author: Dave Martin <Dave.Martin@arm.com>
0004 //
0005 // Utility functions for assembly code.
0006
0007 #include <asm/unistd.h>
0008 #include "assembler.h"
0009
0010 // Print a single character x0 to stdout
0011 // Clobbers x0-x2,x8
0012 function putc
0013 str x0, [sp, #-16]!
0014
0015 mov x0, #1 // STDOUT_FILENO
0016 mov x1, sp
0017 mov x2, #1
0018 mov x8, #__NR_write
0019 svc #0
0020
0021 add sp, sp, #16
0022 ret
0023 endfunction
0024 .globl putc
0025
0026 // Print a NUL-terminated string starting at address x0 to stdout
0027 // Clobbers x0-x3,x8
0028 function puts
0029 mov x1, x0
0030
0031 mov x2, #0
0032 0: ldrb w3, [x0], #1
0033 cbz w3, 1f
0034 add x2, x2, #1
0035 b 0b
0036
0037 1: mov w0, #1 // STDOUT_FILENO
0038 mov x8, #__NR_write
0039 svc #0
0040
0041 ret
0042 endfunction
0043 .globl puts
0044
0045 // Print an unsigned decimal number x0 to stdout
0046 // Clobbers x0-x4,x8
0047 function putdec
0048 mov x1, sp
0049 str x30, [sp, #-32]! // Result can't be > 20 digits
0050
0051 mov x2, #0
0052 strb w2, [x1, #-1]! // Write the NUL terminator
0053
0054 mov x2, #10
0055 0: udiv x3, x0, x2 // div-mod loop to generate the digits
0056 msub x0, x3, x2, x0
0057 add w0, w0, #'0'
0058 strb w0, [x1, #-1]!
0059 mov x0, x3
0060 cbnz x3, 0b
0061
0062 ldrb w0, [x1]
0063 cbnz w0, 1f
0064 mov w0, #'0' // Print "0" for 0, not ""
0065 strb w0, [x1, #-1]!
0066
0067 1: mov x0, x1
0068 bl puts
0069
0070 ldr x30, [sp], #32
0071 ret
0072 endfunction
0073 .globl putdec
0074
0075 // Print an unsigned decimal number x0 to stdout, followed by a newline
0076 // Clobbers x0-x5,x8
0077 function putdecn
0078 mov x5, x30
0079
0080 bl putdec
0081 mov x0, #'\n'
0082 bl putc
0083
0084 ret x5
0085 endfunction
0086 .globl putdecn
0087
0088 // Clobbers x0-x3,x8
0089 function puthexb
0090 str x30, [sp, #-0x10]!
0091
0092 mov w3, w0
0093 lsr w0, w0, #4
0094 bl puthexnibble
0095 mov w0, w3
0096
0097 ldr x30, [sp], #0x10
0098 // fall through to puthexnibble
0099 endfunction
0100 .globl puthexb
0101
0102 // Clobbers x0-x2,x8
0103 function puthexnibble
0104 and w0, w0, #0xf
0105 cmp w0, #10
0106 blo 1f
0107 add w0, w0, #'a' - ('9' + 1)
0108 1: add w0, w0, #'0'
0109 b putc
0110 endfunction
0111 .globl puthexnibble
0112
0113 // x0=data in, x1=size in, clobbers x0-x5,x8
0114 function dumphex
0115 str x30, [sp, #-0x10]!
0116
0117 mov x4, x0
0118 mov x5, x1
0119
0120 0: subs x5, x5, #1
0121 b.lo 1f
0122 ldrb w0, [x4], #1
0123 bl puthexb
0124 b 0b
0125
0126 1: ldr x30, [sp], #0x10
0127 ret
0128 endfunction
0129 .globl dumphex
0130
0131 // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
0132 // Clobbers x0-x3
0133 function memcpy
0134 cmp x2, #0
0135 b.eq 1f
0136 0: ldrb w3, [x1], #1
0137 strb w3, [x0], #1
0138 subs x2, x2, #1
0139 b.ne 0b
0140 1: ret
0141 endfunction
0142 .globl memcpy
0143
0144 // Fill x1 bytes starting at x0 with 0xae (for canary purposes)
0145 // Clobbers x1, x2.
0146 function memfill_ae
0147 mov w2, #0xae
0148 b memfill
0149 endfunction
0150 .globl memfill_ae
0151
0152 // Fill x1 bytes starting at x0 with 0.
0153 // Clobbers x1, x2.
0154 function memclr
0155 mov w2, #0
0156 endfunction
0157 .globl memclr
0158 // fall through to memfill
0159
0160 // Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
0161 // Clobbers x1
0162 function memfill
0163 cmp x1, #0
0164 b.eq 1f
0165
0166 0: strb w2, [x0], #1
0167 subs x1, x1, #1
0168 b.ne 0b
0169
0170 1: ret
0171 endfunction
0172 .globl memfill