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