microblaze: Fix tab indentation in start.S
[oweals/u-boot.git] / arch / microblaze / cpu / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * (C) Copyright 2007 Michal Simek
4  * (C) Copyright 2004 Atmark Techno, Inc.
5  *
6  * Michal  SIMEK <monstr@monstr.eu>
7  * Yasushi SHOJI <yashi@atmark-techno.com>
8  */
9
10 #include <asm-offsets.h>
11 #include <config.h>
12
13         .text
14         .global _start
15 _start:
16         /*
17          * reserve registers:
18          * r10: Stores little/big endian offset for vectors
19          * r2: Stores imm opcode
20          * r3: Stores brai opcode
21          */
22
23         mts     rmsr, r0        /* disable cache */
24
25         addi    r8, r0, __end
26         mts     rslr, r8
27         /* TODO: Redo this code to call board_init_f_*() */
28 #if defined(CONFIG_SPL_BUILD)
29         addi    r1, r0, CONFIG_SPL_STACK_ADDR
30         mts     rshr, r1
31         addi    r1, r1, -4      /* Decrement SP to top of memory */
32 #else
33 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
34         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_VAL(SYS_MALLOC_F_LEN)
35 #else
36         addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
37 #endif
38         mts     rshr, r1
39         addi    r1, r1, -4      /* Decrement SP to top of memory */
40
41         /* Find-out if u-boot is running on BIG/LITTLE endian platform
42          * There are some steps which is necessary to keep in mind:
43          * 1. Setup offset value to r6
44          * 2. Store word offset value to address 0x0
45          * 3. Load just byte from address 0x0
46          * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
47          *     value that's why is on address 0x0
48          * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
49          */
50         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
51         lwi     r7, r0, 0x28
52         swi     r6, r0, 0x28 /* used first unused MB vector */
53         lbui    r10, r0, 0x28 /* used first unused MB vector */
54         swi     r7, r0, 0x28
55
56         /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
57         addi    r2, r0, 0xb0000000      /* hex b000 opcode imm */
58         addi    r3, r0, 0xb8080000      /* hew b808 opcode brai */
59
60 #ifdef CONFIG_SYS_RESET_ADDRESS
61         /* reset address */
62         swi     r2, r0, 0x0     /* reset address - imm opcode */
63         swi     r3, r0, 0x4     /* reset address - brai opcode */
64
65         addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
66         sw      r6, r1, r0
67         lhu     r7, r1, r10
68         rsubi   r8, r10, 0x2
69         sh      r7, r0, r8
70         rsubi   r8, r10, 0x6
71         sh      r6, r0, r8
72 #endif
73
74 #ifdef CONFIG_SYS_USR_EXCEP
75         /* user_vector_exception */
76         swi     r2, r0, 0x8     /* user vector exception - imm opcode */
77         swi     r3, r0, 0xC     /* user vector exception - brai opcode */
78
79         addik   r6, r0, _exception_handler
80         sw      r6, r1, r0
81         /*
82          * BIG ENDIAN memory map for user exception
83          * 0x8: 0xB000XXXX
84          * 0xC: 0xB808XXXX
85          *
86          * then it is necessary to count address for storing the most significant
87          * 16bits from _exception_handler address and copy it to
88          * 0xa address. Big endian use offset in r10=0 that's why is it just
89          * 0xa address. The same is done for the least significant 16 bits
90          * for 0xe address.
91          *
92          * LITTLE ENDIAN memory map for user exception
93          * 0x8: 0xXXXX00B0
94          * 0xC: 0xXXXX08B8
95          *
96          * Offset is for little endian setup to 0x2. rsubi instruction decrease
97          * address value to ensure that points to proper place which is
98          * 0x8 for the most significant 16 bits and
99          * 0xC for the least significant 16 bits
100          */
101         lhu     r7, r1, r10
102         rsubi   r8, r10, 0xa
103         sh      r7, r0, r8
104         rsubi   r8, r10, 0xe
105         sh      r6, r0, r8
106 #endif
107
108         /* interrupt_handler */
109         swi     r2, r0, 0x10    /* interrupt - imm opcode */
110         swi     r3, r0, 0x14    /* interrupt - brai opcode */
111
112         addik   r6, r0, _interrupt_handler
113         sw      r6, r1, r0
114         lhu     r7, r1, r10
115         rsubi   r8, r10, 0x12
116         sh      r7, r0, r8
117         rsubi   r8, r10, 0x16
118         sh      r6, r0, r8
119
120         /* hardware exception */
121         swi     r2, r0, 0x20    /* hardware exception - imm opcode */
122         swi     r3, r0, 0x24    /* hardware exception - brai opcode */
123
124         addik   r6, r0, _hw_exception_handler
125         sw      r6, r1, r0
126         lhu     r7, r1, r10
127         rsubi   r8, r10, 0x22
128         sh      r7, r0, r8
129         rsubi   r8, r10, 0x26
130         sh      r6, r0, r8
131 #endif /* CONFIG_SPL_BUILD */
132
133         /* Flush cache before enable cache */
134         addik   r5, r0, 0
135         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
136         bralid r15, flush_cache
137         nop
138
139         /* enable instruction and data cache */
140         mfs     r12, rmsr
141         ori     r12, r12, 0x1a0
142         mts     rmsr, r12
143
144         /* TODO: Redo this code to call board_init_f_*() */
145 clear_bss:
146         /* clear BSS segments */
147         addi    r5, r0, __bss_start
148         addi    r4, r0, __bss_end
149         cmp     r6, r5, r4
150         beqi    r6, 3f
151 2:
152         swi     r0, r5, 0 /* write zero to loc */
153         addi    r5, r5, 4 /* increment to next loc */
154         cmp     r6, r5, r4 /* check if we have reach the end */
155         bnei    r6, 2b
156 3:      /* jumping to board_init */
157 #ifdef CONFIG_DEBUG_UART
158         bralid  r15, debug_uart_init
159         nop
160 #endif
161 #ifndef CONFIG_SPL_BUILD
162         or      r5, r0, r0      /* flags - empty */
163         addi    r31, r0, _gd
164 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
165         addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
166         swi     r6, r31, GD_MALLOC_BASE
167 #endif
168         brai    board_init_f
169 #else
170         addi    r31, r0, _gd
171 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
172         addi    r6, r0, CONFIG_SPL_STACK_ADDR
173         swi     r6, r31, GD_MALLOC_BASE
174 #endif
175         brai    board_init_r
176 #endif
177 1:      bri     1b
178
179  .section .bss
180 .align 4
181 _gd:
182          .space  GENERATED_GBL_DATA_SIZE
183
184 #ifndef CONFIG_SPL_BUILD
185 /*
186  * Read 16bit little endian
187  */
188         .text
189         .global in16
190         .ent    in16
191         .align  2
192 in16:   lhu     r3, r0, r5
193         bslli   r4, r3, 8
194         bsrli   r3, r3, 8
195         andi    r4, r4, 0xffff
196         or      r3, r3, r4
197         rtsd    r15, 8
198         sext16  r3, r3
199         .end    in16
200
201 /*
202  * Write 16bit little endian
203  * first parameter(r5) - address, second(r6) - short value
204  */
205         .text
206         .global out16
207         .ent    out16
208         .align  2
209 out16:  bslli   r3, r6, 8
210         bsrli   r6, r6, 8
211         andi    r3, r3, 0xffff
212         or      r3, r3, r6
213         sh      r3, r0, r5
214         rtsd    r15, 8
215         or      r0, r0, r0
216         .end    out16
217
218 /*
219  * Relocate u-boot
220  */
221         .text
222         .global relocate_code
223         .ent    relocate_code
224         .align  2
225 relocate_code:
226         /*
227          * r5 - start_addr_sp
228          * r6 - new_gd
229          * r7 - reloc_addr
230          */
231         addi    r1, r5, 0 /* Start to use new SP */
232         addi    r31, r6, 0 /* Start to use new GD */
233
234         add     r23, r0, r7 /* Move reloc addr to r23 */
235         /* Relocate text and data - r12 temp value */
236         addi    r21, r0, _start
237         addi    r22, r0, __end - 4 /* Include BSS too */
238
239         rsub    r6, r21, r22
240         or      r5, r0, r0
241 1:      lw      r12, r21, r5 /* Load u-boot data */
242         sw      r12, r23, r5 /* Write zero to loc */
243         cmp     r12, r5, r6 /* Check if we have reach the end */
244         bneid   r12, 1b
245         addi    r5, r5, 4 /* Increment to next loc - relocate code */
246
247         /* R23 points to the base address. */
248         add     r23, r0, r7 /* Move reloc addr to r23 */
249         addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
250         rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
251
252         addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
253         lwi     r7, r0, 0x28
254         swi     r6, r0, 0x28 /* used first unused MB vector */
255         lbui    r10, r0, 0x28 /* used first unused MB vector */
256         swi     r7, r0, 0x28
257
258 #ifdef CONFIG_SYS_USR_EXCEP
259         addik   r6, r0, _exception_handler
260         addk    r6, r6, r23 /* add offset */
261         sw      r6, r1, r0
262         lhu     r7, r1, r10
263         rsubi   r8, r10, 0xa
264         sh      r7, r0, r8
265         rsubi   r8, r10, 0xe
266         sh      r6, r0, r8
267 #endif
268         addik   r6, r0, _hw_exception_handler
269         addk    r6, r6, r23 /* add offset */
270         sw      r6, r1, r0
271         lhu     r7, r1, r10
272         rsubi   r8, r10, 0x22
273         sh      r7, r0, r8
274         rsubi   r8, r10, 0x26
275         sh      r6, r0, r8
276
277         addik   r6, r0, _interrupt_handler
278         addk    r6, r6, r23 /* add offset */
279         sw      r6, r1, r0
280         lhu     r7, r1, r10
281         rsubi   r8, r10, 0x12
282         sh      r7, r0, r8
283         rsubi   r8, r10, 0x16
284         sh      r6, r0, r8
285
286         /* Check if GOT exist */
287         addik   r21, r23, _got_start
288         addik   r22, r23, _got_end
289         cmpu    r12, r21, r22
290         beqi    r12, 2f /* No GOT table - jump over */
291
292         /* Skip last 3 entries plus 1 because of loop boundary below */
293         addik   r22, r22, -0x10
294
295         /* Relocate the GOT. */
296 3:      lw      r12, r21, r0 /* Load entry */
297         addk    r12, r12, r23 /* Add reloc offset */
298         sw      r12, r21, r0 /* Save entry back */
299
300         cmpu    r12, r21, r22 /* Check if this cross boundary */
301         bneid   r12, 3b
302         addik   r21. r21, 4
303
304         /* Update pointer to GOT */
305         mfs     r20, rpc
306         addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
307         addk    r20, r20, r23
308
309         /* Flush caches to ensure consistency */
310         addik   r5, r0, 0
311         addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
312         bralid  r15, flush_cache
313         nop
314
315 2:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
316         addi    r6, r0, CONFIG_SYS_TEXT_BASE
317         addi    r12, r23, board_init_r
318         bra     r12 /* Jump to relocated code */
319
320         .end    relocate_code
321 #endif