xref: /openbmc/qemu/tests/tcg/nios2/boot.S (revision ca61e750)
1/*
2 * Minimal Nios2 system boot code.
3 *
4 * Copyright Linaro Ltd 2022
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include "semicall.h"
9
10        .text
11	.set	noat
12
13_start:
14	/* Linker script defines stack at end of ram. */
15	movia	sp, __stack
16
17	/* Install trampoline to _fast_tlb_miss at hardcoded vector. */
18	movia	r4, 0xc0000100
19	movia	r5, _ftm_tramp
20	movi	r6, .L__ftm_end - _ftm_tramp
21	call	memcpy
22
23	/* Zero the bss to satisfy C. */
24	movia	r4, __bss_start
25	movia	r6, __bss_end
26	sub	r6, r6, r4
27	movi	r5, 0
28	call	memset
29
30	/* Test! */
31	call	main
32
33	/* Exit with main's return value. */
34	movi	r4, HOSTED_EXIT
35	mov	r5, r2
36	semihosting_call
37
38	.globl	_start
39	.type	_start, @function
40	.size	_start, . - _start
41
42_ftm_tramp:
43	movia	et, _fast_tlb_miss
44	jmp	et
45.L__ftm_end:
46
47	.type	_ftm_tramp, @function
48	.size	_ftm_tramp, . - _ftm_tramp
49
50#define dst	r4
51#define src	r5
52#define len	r6
53
54memcpy:
55	/* Store return value right away, per API */
56	mov	r2, dst
57
58	/* Check for both dst and src aligned. */
59	or	at, dst, src
60	andi	at, at, 3
61	bne	at, zero, .L_mc_test1
62
63	/* Copy blocks of 8. */
64
65	movi	at, 8
66	bltu	len, at, .L_mc_test4
67
68.L_mc_loop8:
69	ldw	r8, 0(src)
70	ldw	r9, 4(src)
71	addi	src, src, 8
72	addi	dst, dst, 8
73	subi	len, len, 8
74	stw	r8, -8(dst)
75	stw	r9, -4(dst)
76	bgeu	len, at, .L_mc_loop8
77
78	/* Copy final aligned block of 4. */
79
80.L_mc_test4:
81	movi	at, 4
82	bltu	len, at, .L_mc_test1
83
84	ldw	r8, 0(src)
85	addi	src, src, 4
86	addi	dst, dst, 4
87	subi	len, len, 4
88	stw	r8, -4(dst)
89
90	/* Copy single bytes to finish. */
91
92.L_mc_test1:
93	beq	len, zero, .L_mc_done
94
95.L_mc_loop1:
96	ldb	r8, 0(src)
97	addi	src, src, 1
98	addi	dst, dst, 1
99	subi	len, len, 1
100	stb	r8, -1(dst)
101	bne	len, zero, .L_mc_loop1
102
103.L_mc_done:
104	ret
105
106#undef dst
107#undef src
108#undef len
109
110	.global	memcpy
111	.type	memcpy, @function
112	.size	memcpy, . - memcpy
113
114#define dst	r4
115#define val	r5
116#define len	r6
117
118memset:
119	/* Store return value right away, per API */
120	mov	r2, dst
121
122	/* Check for small blocks; fall back to bytewise. */
123	movi	r3, 8
124	bltu	len, r3, .L_ms_test1
125
126	/* Replicate the byte across the word. */
127	andi	val, val, 0xff
128	slli	at, val, 8
129	or	val, val, at
130	slli	at, val, 16
131	or	val, val, at
132
133	/* Check for destination alignment; realign if needed. */
134	andi	at, dst, 3
135	bne	at, zero, .L_ms_align
136
137	/* Set blocks of 8. */
138
139.L_ms_loop8:
140	stw	val, 0(dst)
141	stw	val, 4(dst)
142	addi	dst, dst, 8
143	subi	len, len, 8
144	bgeu	len, r3, .L_ms_loop8
145
146	/* Set final aligned block of 4. */
147
148.L_ms_test4:
149	movi	at, 4
150	bltu	len, at, .L_ms_test1
151
152	stw	r8, 0(dst)
153	addi	dst, dst, 4
154	subi	len, len, 4
155	stw	r8, -4(dst)
156
157	/* Set single bytes to finish. */
158
159.L_ms_test1:
160	beq	len, zero, .L_ms_done
161
162.L_ms_loop1:
163	stb	r8, 0(dst)
164	addi	dst, dst, 1
165	subi	len, len, 1
166	bne	len, zero, .L_ms_loop1
167
168.L_ms_done:
169	ret
170
171	/* Realign for a large block, len >= 8. */
172.L_ms_align:
173	andi	at, dst, 1
174	beq	at, zero, 2f
175
176	stb	val, 0(dst)
177	addi	dst, dst, 1
178	subi	len, len, 1
179
1802:	andi	at, dst, 2
181	beq	at, zero, 4f
182
183	sth	val, 0(dst)
184	addi	dst, dst, 2
185	subi	len, len, 2
186
1874:	bgeu	len, r3, .L_ms_loop8
188	br	.L_ms_test4
189
190#undef dst
191#undef val
192#undef len
193
194	.global	memset
195	.type	memset, @function
196	.size	memset, . - memset
197
198/*
199 * void __sys_outc(char c);
200 */
201__sys_outc:
202	subi	sp, sp, 16
203	stb	r4, 0(sp)	/* buffer[0] = c */
204	movi	at, 1
205	stw	at, 4(sp)	/* STDOUT_FILENO */
206	stw	sp, 8(sp)	/* buffer */
207	stw	at, 12(sp)	/* len */
208
209	movi	r4, HOSTED_WRITE
210	addi	r5, sp, 4
211	semihosting_call
212
213	addi	sp, sp, 16
214	ret
215
216	.global	__sys_outc
217	.type	__sys_outc, @function
218	.size	__sys_outc, . - __sys_outc
219