| /* Linux SPARC/UltraSPARC Loader Bootstrap |
| |
| Copyright (C) 1996,1997,1998,2000 Jakub Jelinek |
| 1998 Jan Vondrak |
| 1996 Pete A. Zaitcev |
| 1996 Miguel de Icaza |
| 2001 Ben Collins |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
| USA. */ |
| |
| #define COPY jmpl %o7 + (copy - _start), %l7 |
| |
| #ifdef SUPERTILO |
| #define STACK_BASE 0xa00000 |
| #else |
| #ifndef LARGETILO |
| #define STACK_BASE 0x400000 |
| #else |
| #define STACK_BASE 0x500000 |
| #endif |
| #endif |
| |
| .text |
| .global _start |
| .global image_table |
| .align 16 |
| _start: |
| call 1f |
| mov %o7, %l0 |
| |
| image_table: |
| .skip 64 /* struct ImageInfo image_table[4] */ |
| |
| 1: |
| /* Move ourselves up */ ! %l0 = original start |
| set __bss_start + 16, %i1 ! %i1 = original end |
| set _start, %l1 ! %i0 = %l1 = relocated start |
| mov %l1, %i0 ! %l2 = code length |
| COPY |
| sub %i1, %l1, %l2 |
| |
| /* Jump to relocated code */ |
| sethi %hi(_end), %l0 |
| jmpl %i0 + (jumphere - _start), %g0 |
| or %l0, %lo(_end), %l0 ! %l0 = _end |
| |
| .align 32 |
| jumphere: |
| /* Clear BSS */ |
| 5: add %l0, %i3, %l0 |
| add %i1, %i3, %i1 |
| andcc %i1, 4, %g0 |
| sub %l0, %i1, %i2 ! %i2 = BSS length |
| be 1f |
| mov %g0, %g1 |
| |
| st %g0, [%i1] |
| add %i1, 4, %i1 |
| 1: |
| subcc %i2, 32, %i2 |
| std %g0, [%i1] |
| std %g0, [%i1 + 8] |
| std %g0, [%i1 + 16] |
| std %g0, [%i1 + 24] |
| bgu 1b |
| add %i1, 32, %i1 |
| |
| tst %o4 ! if not Ultra, |
| be 1f ! skip %pstate modification |
| nop |
| |
| rdpr %pstate, %l1 |
| or %l1, 8, %l1 |
| wrpr %l1, 0, %pstate |
| 1: |
| |
| ! Set up a stack |
| setup_stack: |
| set STACK_BASE, %l1 |
| save %l1, -64, %sp |
| |
| ! Call my_main() to start the whole thingie up |
| |
| 0: call flush_icache |
| mov %i6, %o2 ! Cif sp on sun4u |
| mov %i4, %o1 ! Cif handler on sun4u |
| call my_main |
| mov %i0, %o0 ! Prom vector or cifh on sun4m |
| call flush_icache |
| nop |
| jmpl %o0 + %g0, %g0 ! Jump to return address from my_main() |
| restore |
| |
| /* l0 from, l1 to, l2 len, l7 ret. Returns from + len in l0 */ |
| copy: |
| ld [%l0], %l3 |
| ld [%l0 + 4], %l4 |
| ld [%l0 + 8], %l5 |
| ld [%l0 + 12], %l6 |
| subcc %l2, 16, %l2 |
| add %l0, 16, %l0 |
| st %l3, [%l1] |
| st %l4, [%l1 + 4] |
| st %l5, [%l1 + 8] |
| st %l6, [%l1 + 12] |
| bgu copy |
| add %l1, 16, %l1 |
| |
| jmpl %l7 + 8, %g0 |
| nop |
| |
| flush_icache: |
| tst %i4 /* quit unless it's Sun4u */ |
| be 0f |
| nop |
| rdpr %ver, %l0 |
| srlx %l0, (32 + 16), %l1 |
| cmp %l1, 0x3e |
| bne,pt %xcc, 99f |
| sllx %l0, 16, %l0 |
| srlx %l0, (32 + 16), %l1 |
| cmp %l1, 0x14 |
| bgeu,pt %xcc, 0f /* quit if Ultra-III or derivative */ |
| nop |
| 99: |
| rdpr %ver, %l0 |
| srlx %l0, 32, %l0 |
| sethi %hi(0x40003), %l1 |
| or %l1, %lo(0x40003), %l1 |
| cmp %l0, %l1 |
| be 0f /* quit if HAL SPARC64-III */ |
| nop |
| sethi %hi(0x40004), %l1 |
| or %l1, %lo(0x40004), %l1 |
| cmp %l0, %l1 |
| be 0f /* quit if HAL SPARC64-IV */ |
| nop |
| clr %l0 |
| sethi %hi(16384), %l1 |
| stxa %g0, [%l0] 0x67 /* ASI_IC_TAG */ |
| 1: |
| add %l0, 32, %l0 |
| cmp %l0, %l1 |
| blu,a,pt %xcc, 1b |
| stxa %g0, [%l0] 0x67 /* ASI_IC_TAG */ |
| 0: |
| retl |
| nop |
| |
| .section ".rodata" |
| .word _start |