Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / tests / tcg / nios2 / boot.S
blobf6771cbc81af74c85ad6151951ab5feedba90702
1 /*
2  * Minimal Nios2 system boot code.
3  *
4  * Copyright Linaro Ltd 2022
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  */
8 #include "semicall.h"
10         .text
11         .set    noat
13 _start:
14         /* Linker script defines stack at end of ram. */
15         movia   sp, __stack
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
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
30         /* Test! */
31         call    main
33         /* Exit with main's return value. */
34         movi    r4, HOSTED_EXIT
35         mov     r5, r2
36         semihosting_call
38         .globl  _start
39         .type   _start, @function
40         .size   _start, . - _start
42 _ftm_tramp:
43         movia   et, _fast_tlb_miss
44         jmp     et
45 .L__ftm_end:
47         .type   _ftm_tramp, @function
48         .size   _ftm_tramp, . - _ftm_tramp
50 #define dst     r4
51 #define src     r5
52 #define len     r6
54 memcpy:
55         /* Store return value right away, per API */
56         mov     r2, dst
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
63         /* Copy blocks of 8. */
65         movi    at, 8
66         bltu    len, at, .L_mc_test4
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
78         /* Copy final aligned block of 4. */
80 .L_mc_test4:
81         movi    at, 4
82         bltu    len, at, .L_mc_test1
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)
90         /* Copy single bytes to finish. */
92 .L_mc_test1:
93         beq     len, zero, .L_mc_done
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
103 .L_mc_done:
104         ret
106 #undef dst
107 #undef src
108 #undef len
110         .global memcpy
111         .type   memcpy, @function
112         .size   memcpy, . - memcpy
114 #define dst     r4
115 #define val     r5
116 #define len     r6
118 memset:
119         /* Store return value right away, per API */
120         mov     r2, dst
122         /* Check for small blocks; fall back to bytewise. */
123         movi    r3, 8
124         bltu    len, r3, .L_ms_test1
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
133         /* Check for destination alignment; realign if needed. */
134         andi    at, dst, 3
135         bne     at, zero, .L_ms_align
137         /* Set blocks of 8. */
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
146         /* Set final aligned block of 4. */
148 .L_ms_test4:
149         movi    at, 4
150         bltu    len, at, .L_ms_test1
152         stw     r8, 0(dst)
153         addi    dst, dst, 4
154         subi    len, len, 4
155         stw     r8, -4(dst)
157         /* Set single bytes to finish. */
159 .L_ms_test1:
160         beq     len, zero, .L_ms_done
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
168 .L_ms_done:
169         ret
171         /* Realign for a large block, len >= 8. */
172 .L_ms_align:
173         andi    at, dst, 1
174         beq     at, zero, 2f
176         stb     val, 0(dst)
177         addi    dst, dst, 1
178         subi    len, len, 1
180 2:      andi    at, dst, 2
181         beq     at, zero, 4f
183         sth     val, 0(dst)
184         addi    dst, dst, 2
185         subi    len, len, 2
187 4:      bgeu    len, r3, .L_ms_loop8
188         br      .L_ms_test4
190 #undef dst
191 #undef val
192 #undef len
194         .global memset
195         .type   memset, @function
196         .size   memset, . - memset
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 */
209         movi    r4, HOSTED_WRITE
210         addi    r5, sp, 4
211         semihosting_call
213         addi    sp, sp, 16
214         ret
216         .global __sys_outc
217         .type   __sys_outc, @function
218         .size   __sys_outc, . - __sys_outc