Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / start.S
1 /* 
2  *      <start.S>
3  *      
4  *     BIOS start code for Open Hack'Ware.
5  *   
6  *   Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr)
7  *   
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License V2
10  *   as published by the Free Software Foundation
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #define ASSEMBLY_CODE
23 #include "bios.h"
24
25 .section .start, "ax"
26 .align 2
27
28 .globl _start
29 _start:
30         /* Save our stack pointer */
31         lis    r11, saved_params@h                           ;
32         ori    r11, r11, saved_params@l                      ;
33         stw    r1, 0(r11)                                    ;
34         /* Fill space from _bss_start to _ram_start with zeroes */
35         lis    r11, _bss_start@h                             ;
36         ori    r11, r11, _bss_start@l                        ;
37         lis    r12, _ram_start@h                             ;
38         ori    r12, r12, _ram_start@l                        ;
39         subf   r12, r11, r12                                 ;
40         srawi  r12, r12, 2                                   ;
41         cmpi   0, r12, 0                                     ;
42         beq    _bss_done                                     ;
43         mtctr  r12                                           ;
44         subi   r11, r11, 4                                   ;
45         li     r12, 0                                        ;
46 _bss_loop:
47         stwu   r12, 4(r11)                                   ;
48         bdnz   _bss_loop                                     ;
49 _bss_done:
50         /* Now, we have a real C environment: call main */
51         bl     main                                          ;
52         /* If we return, stop */
53 .globl bug
54 bug:
55         li     r0, 0x80                                      ;
56         mtlr   r0                                            ;
57         blr                                                  ;
58 _return_loop:
59         b      _return_loop                                  ;
60
61 .section .data
62 .align 2
63 saved_params:
64         .long 0x00000000 /* OF stack     */
65         .long 0x00000000 /* client stack */
66         .long 0x00000000 /* client link  */
67         
68 .section .text
69 .align 2
70
71 .globl transfer_handler
72 transfer_handler:
73         /* Build a new stack room and launch loaded image
74          * void transfer_handler (void *residual, void *load_addr,
75          *                        void *OF_entry, void *bootinfos,
76          *                        void *cmdline, void *unused,
77          *                        void *nip, void *stack_base);
78          */
79         mfmsr  r0                                            ;
80         mtspr  SRR1, r0                                      ;
81         mtspr  SRR0, r9                                      ;
82         li     r0, 0                                         ;
83         mr     r1, r10                                       ;
84         stw    r1, -16(r1)                                   ;
85         stwu   r0, -4(r1)                                    ;
86         stwu   r0, -4(r1)                                    ;
87         stwu   r0, -4(r1)                                    ;
88         stwu   r0, -4(r1)                                    ;
89         /* Skip frame pointer */        
90         stwu   r0, -8(r1)                                    ;
91         stwu   r0, -4(r1)                                    ;
92         stwu   r0, -4(r1)                                    ;
93         rfi                                                  ;
94         /* Should never return, but who knows... */
95         bl     bug                                           ;
96
97 .globl  OF_entry
98 OF_entry:
99         /* Save the stack pointer and get our own one */
100         lis    r11, saved_params@h                           ;
101         ori    r11, r11, saved_params@l                      ;
102         mflr   r12                                           ;
103         stw    r12, 8(r11)                                   ;
104         stw    r1, 4(r11)                                    ;
105         lwz    r1, 0(r11)                                    ;
106         bl     OF_client_entry                               ;
107         lis    r11, saved_params@h                           ;
108         ori    r11, r11, saved_params@l                      ;
109         lwz    r12, 8(r11)                                   ;
110         mtlr   r12                                           ;
111         lwz    r1, 4(r11)                                    ;
112         blr                                                  ;
113         
114         /* PPC helpers */
115 .globl mfmsr
116 mfmsr:
117         /* uint32_t mfmsr (void); */
118         mfmsr  r3                                            ;
119         blr                                                  ;
120 .globl mtmsr
121 mtmsr:
122         /* void mtmsr (uint32_t msr); */
123         lis    r0, _mtmsr_rfi@h                              ;
124         ori    r0, r0, _mtmsr_rfi@l                          ;
125         mtspr  26, r0                                        ;
126         mtspr  27, r3                                        ;
127         rfi                                                  ;
128 _mtmsr_rfi:
129         blr                                                  ;
130 .globl MMU_on
131 MMU_on:
132         /* void MMU_on (void); */
133         stwu   r1, -16(r1)                                   ;
134         mflr   r0                                            ;
135         stw    r0, 20(r1)                                    ;
136         mfmsr  r3                                            ;
137         ori    r3, r3, 0x30                                  ;
138         bl     mtmsr                                         ;
139         lwz    r0, 20(r1)                                    ;
140         mtlr   r0                                            ;
141         addi   r1, r1, 16                                    ;
142         blr                                                  ;
143         
144 .globl MMU_off
145 MMU_off:
146         /* void MMU_off (void); */
147         stwu   r1, -16(r1)                                   ;
148         mflr   r0                                            ;
149         stw    r0, 20(r1)                                    ;
150         mfmsr  r3                                            ;
151         andi.  r3, r3, 0xFFCF                                ;
152         bl     mtmsr                                         ;
153         lwz    r0, 20(r1)                                    ;
154         mtlr   r0                                            ;
155         addi   r1, r1, 16                                    ;
156         blr                                                  ;
157         
158 .globl mfpvr
159 mfpvr:
160         /* uint32_t mfpvr (void); */
161         mfpvr  r3                                            ;
162         blr                                                  ;
163
164 .globl mftb
165 mftb:
166         /* void mftb (uint32_t *tb); */
167         stwu   r1, -16(r1)                                   ;
168         stw    r11, 12(r1)                                   ;
169         stw    r12,  8(r1)                                   ;
170         /* No need to save lr */
171 _tb_loop:
172         mftbu  r11                                           ;
173         mftb   r12                                           ;
174         mftbu  r0                                            ;
175         cmpw   r0, r11                                       ;
176         bne    _tb_loop                                      ;
177         stw    r11,  0(r3)                                   ;
178         stw    r12,  4(r3)                                   ;
179         lwz    r12,  8(r1)                                   ;
180         lwz    r11, 12(r1)                                   ;
181         addi   r1, r1, 16                                    ;
182         blr                                                  ;      
183
184         /* IO helpers */
185 .globl inb
186 inb:
187         /* uint32_t inb (uint16_t port); */
188         stwu   r1, -16(r1)                                   ;
189         stw    r11, 12(r1)                                   ;
190         lis    r11, isa_io_base@h                            ;
191         ori    r11, r11, isa_io_base@l                       ;
192         lwz    r11, 0(r11)                                   ;
193         add    r3, r3, r11                                   ;
194         lbz    r3, 0(r3)                                     ;
195         eieio                                                ;
196         lwz    r11, 12(r1)                                   ;
197         addi   r1, r1, 16                                    ;
198         blr                                                  ;
199
200 .globl outb
201 outb:
202         /* void outb (uint16_t port, uint32_t val); */
203         stwu   r1, -16(r1)                                   ;
204         stw    r11, 12(r1)                                   ;
205         lis    r11, isa_io_base@h                            ;
206         ori    r11, r11, isa_io_base@l                       ;
207         lwz    r11, 0(r11)                                   ;
208         add    r3, r3, r11                                   ;
209         eieio                                                ;
210         stb    r4, 0(r3)                                     ;
211         lwz    r11, 12(r1)                                   ;
212         addi   r1, r1, 16                                    ;
213         blr                                                  ;
214
215 .globl inw
216 inw:
217         /* uint32_t inw (uint16_t port); */
218         stwu   r1, -16(r1)                                   ;
219         stw    r11, 12(r1)                                   ;
220         lis    r11, isa_io_base@h                            ;
221         ori    r11, r11, isa_io_base@l                       ;
222         lwz    r11, 0(r11)                                   ;
223         add    r3, r3, r11                                   ;
224         lhbrx  r3, 0, r3                                     ;
225         eieio                                                ;
226         lwz    r11, 12(r1)                                   ;
227         addi   r1, r1, 16                                    ;
228         blr                                                  ;
229
230 .globl outw
231 outw:
232         /* void outw (uint16_t port, uint32_t val); */
233         stwu   r1, -16(r1)                                   ;
234         stw    r11, 12(r1)                                   ;
235         lis    r11, isa_io_base@h                            ;
236         ori    r11, r11, isa_io_base@l                       ;
237         lwz    r11, 0(r11)                                   ;
238         add    r3, r3, r11                                   ;
239         eieio                                                ;
240         sthbrx r4, 0, r3                                     ;
241         lwz    r11, 12(r1)                                   ;
242         addi   r1, r1, 16                                    ;
243         blr                                                  ;
244
245 .globl inl
246 inl:
247         /* uint32_t inl (uint16_t port); */
248         stwu   r1, -16(r1)                                   ;
249         stw    r11, 12(r1)                                   ;
250         lis    r11, isa_io_base@h                            ;
251         ori    r11, r11, isa_io_base@l                       ;
252         lwz    r11, 0(r11)                                   ;
253         add    r3, r3, r11                                   ;
254         lwbrx  r3, 0, r3                                     ;
255         eieio                                                ;
256         lwz    r11, 12(r1)                                   ;
257         addi   r1, r1, 16                                    ;
258         blr                                                  ;
259
260 .globl outl
261 outl:
262         /* void outl (uint16_t port, uint32_t val); */
263         stwu   r1, -16(r1)                                   ;
264         stw    r11, 12(r1)                                   ;
265         lis    r11, isa_io_base@h                            ;
266         ori    r11, r11, isa_io_base@l                       ;
267         lwz    r11, 0(r11)                                   ;
268         add    r3, r3, r11                                   ;
269         eieio                                                ;
270         stwbrx r4, 0, r3                                     ;
271         lwz    r11, 12(r1)                                   ;
272         addi   r1, r1, 16                                    ;
273         blr                                                  ;
274
275 .globl eieio
276 eieio:
277         eieio                                                ;
278         blr                                                  ;
279         
280         /* Misc helpers */
281 .globl ldswap16
282 ldswap16:
283         /* uint16_t ldswap16 (uint16_t *addr); */
284         lhbrx  r3, 0, r3                                     ;
285         blr                                                  ;
286
287 .globl stswap16
288 stswap16:
289         /* void stswap16 (void *addr, uint16_t val); */
290         sthbrx r4, 0, r3                                     ;
291         blr                                                  ;
292
293 .globl ldswap32
294 ldswap32:
295         /* uint32_t ldswap32 (uint32_t *addr); */
296         lwbrx  r3, 0, r3                                     ;
297         blr                                                  ;
298
299 .globl stswap32
300 stswap32:
301         /* void stswap32 (void *addr, uint32_t val); */
302         stwbrx r4, 0, r3                                     ;
303         blr                                                  ;
304
305 .globl mul64
306 mul64:
307         /* void mul64 (uint32_t *ret, uint32_t a, uint32_t b); */
308         mulhwu r0, r4, r5                                    ;
309         stw    r0, 0(r3)                                     ;
310         mullw  r0, r4, r5                                    ;
311         stw    r0, 4(r3)                                     ;
312         blr                                                  ;
313
314 .globl add64
315 add64:
316         /* void add64 (uint32_t *ret, uint32_t *a, uint32_t *b); */
317         stwu   r1, -16(r1)                                   ;
318         stw    r11, 12(r1)                                   ;
319         stw    r12,  8(r1)                                   ;
320         lwz    r11,  4(r4)                                   ;
321         lwz    r12,  4(r5)                                   ;
322         addc   r0, r11, r12                                  ;
323         stw    r0,   4(r3)                                   ;
324         lwz    r11,  0(r4)                                   ;
325         lwz    r12,  0(r5)                                   ;
326         adde   r0, r11, r12                                  ;
327         stw    r0,   0(r3)                                   ;
328         lwz    r12,  8(r1)                                   ;
329         lwz    r11,  4(r1)                                   ;
330         addi   r1, r1, 16                                    ;
331         blr                                                  ;
332
333 .globl setjmp
334 setjmp:
335         /* int setjmp (jmp_buf env); */
336         /* save gprs */
337         stmw   r0, 0(r3)                                     ;
338         /* save lr, ctr, xer and ccr */
339         mflr   r0                                            ;
340         stw    r0, 0x80(r3)                                  ;
341         mfctr  r0                                            ;
342         stw    r0, 0x84(r3)                                  ;
343         mfxer  r0                                            ;
344         stw    r0, 0x88(r3)                                  ;
345         mfcr   r0                                            ;
346         stw    r0, 0x8C(r3)                                  ;
347         /* return 0 */
348         li     r3, 0                                         ;
349         blr                                                  ;
350
351 .globl longjmp
352 longjmp:
353         /* void longjmp (jmp_buf env, int val); */
354         /* Let's pretend env is our stack */
355         mr     r1, r3                                        ;
356         /* Be sure we won't return 0 */
357         cmpi   0, r4, 0                                      ;
358         bne    _longjmp_cont                                 ;
359         addi   r4, r4, 1                                     ;
360 _longjmp_cont:
361         /* Store return value in jmp_buf */
362         stw    r4, 0x0C(r1)                                  ;
363         /* restore lr, ctr, xer and ccr */
364         lwz    r0, 0x80(r1)                                  ;
365         mtlr   r0                                            ;
366         lwz    r0, 0x84(r1)                                  ;
367         mtctr  r0                                            ;
368         lwz    r0, 0x88(r1)                                  ;
369         mtxer  r0                                            ;
370         lwz    r0, 0x8C(r1)                                  ;
371         mtcr   r0                                            ;
372         /* Restore r2 to r31 */
373         lmw    r2, 0x08(r1)                                  ;
374         /* Restore r0 (could forget it...) */
375         lwz    r0, 0x00(r1)                                  ;
376         /* Restore stack */
377         lwz    r1, 0x04(r1)                                  ;
378         /* Return */
379         blr                                                  ;