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