| /* |
| * Creation Date: <2001/06/16 21:30:18 samuel> |
| * Time-stamp: <2003/04/04 16:32:06 samuel> |
| * |
| * <init.S> |
| * |
| * Asm glue for ELF images run inside MOL |
| * |
| * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) |
| * |
| * 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 |
| * |
| */ |
| |
| #include "asm/asmdefs.h" |
| #include "asm/processor.h" |
| #include "osi.h" |
| |
| /************************************************************************/ |
| /* Macros */ |
| /************************************************************************/ |
| |
| #define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ; |
| #define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v |
| |
| #define EXCEPTION_PREAMBLE \ |
| mtsprg1 r1 ; /* scratch */ \ |
| mfsprg0 r1 ; /* exception stack in sprg0 */ \ |
| addi r1,r1,-80 ; /* push exception frame */ \ |
| \ |
| stw r0,0(r1) ; /* save r0 */ \ |
| mfsprg1 r0 ; \ |
| stw r0,4(r1) ; /* save r1 */ \ |
| stw r2,8(r1) ; /* save r2 */ \ |
| stw r3,12(r1) ; /* save r3 */ \ |
| stw r4,16(r1) ; \ |
| stw r5,20(r1) ; \ |
| stw r6,24(r1) ; \ |
| stw r7,28(r1) ; \ |
| stw r8,32(r1) ; \ |
| stw r9,36(r1) ; \ |
| stw r10,40(r1) ; \ |
| stw r11,44(r1) ; \ |
| stw r12,48(r1) ; \ |
| \ |
| mflr r0 ; \ |
| stw r0,52(r1) ; \ |
| mfcr r0 ; \ |
| stw r0,56(r1) ; \ |
| mfctr r0 ; \ |
| stw r0,60(r1) ; \ |
| mfxer r0 ; \ |
| stw r0,64(r1) ; \ |
| \ |
| /* 76(r1) unused */ \ |
| addi r1,r1,-16 ; /* call conventions uses 0(r1) and 4(r1)... */ |
| |
| |
| /************************************************************************/ |
| /* stack space */ |
| /************************************************************************/ |
| |
| .section .bss |
| .balign 32 |
| .space 32*1024 // 32 K client stack |
| client_stack: |
| .space 128 |
| |
| .space 64*1024 // 64 K stack |
| stack: .space 64 |
| |
| .space 32*1024 // 32 K exception stack |
| estack: .space 128 |
| |
| |
| /************************************************************************/ |
| /* entry */ |
| /************************************************************************/ |
| |
| .text |
| GLOBL(_start): |
| li r0,0 |
| mtmsr r0 |
| |
| lis r1,HA(estack) |
| addi r1,r1,LO(estack) |
| mtsprg0 r1 // setup exception stack |
| lis r1,HA(stack) |
| addi r1,r1,LO(stack) |
| |
| // copy exception vectors |
| lis r3,HA(__vectors) |
| addi r3,r3,LO(__vectors) |
| li r4,0 |
| li r5,__vectors_end - __vectors + 16 |
| rlwinm r5,r5,0,0,28 |
| 1: lwz r6,0(r3) |
| lwz r7,4(r3) |
| lwz r8,8(r3) |
| lwz r9,12(r3) |
| stw r6,0(r4) |
| stw r7,4(r4) |
| stw r8,8(r4) |
| stw r9,12(r4) |
| dcbst 0,r4 |
| sync |
| icbi 0,r4 |
| sync |
| addi r5,r5,-16 |
| addi r3,r3,16 |
| addi r4,r4,16 |
| cmpwi r5,0 |
| bgt 1b |
| isync |
| |
| bl setup_mmu |
| bl entry |
| 1: nop |
| b 1b |
| |
| |
| /* According to IEEE 1275, PPC bindings: |
| * |
| * MSR = FP, ME + (DR|IR) |
| * r1 = stack (32 K + 32 bytes link area above) |
| * r5 = clint interface handler |
| * r6 = address of client program arguments (unused) |
| * r7 = length of client program arguments (unsed) |
| */ |
| saved_stack: |
| .long 0 |
| /* void call_elf( entry ) */ |
| GLOBL(call_elf): |
| mflr r0 |
| stwu r1,-16(r1) |
| stw r0,20(r1) |
| mtlr r3 |
| lis r8,HA(saved_stack) |
| addi r8,r8,LO(saved_stack) // save our stack pointer |
| stw r1,0(r8) |
| lis r1,HA(client_stack) |
| addi r1,r1,LO(client_stack) |
| lis r5,HA(of_client_callback) |
| addi r5,r5,LO(of_client_callback) // r5 = callback |
| li r6,0 // r6 = address of client program arguments (unused) |
| li r7,0 // r7 = length of client program arguments (unused) |
| li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR |
| mtmsr r0 |
| blrl |
| |
| lis r8,HA(saved_stack) |
| addi r8,r8,LO(saved_stack) // restore stack pointer |
| mr r1,r8 |
| lwz r0,20(r1) |
| mtlr r0 |
| addi r1,r1,16 |
| // XXX: should restore r12-r31 etc.. |
| // we should not really come here though |
| blr |
| |
| GLOBL(of_client_callback): |
| lis r4,HA(saved_stack) |
| addi r4,r4,LO(saved_stack) |
| lwz r4,0(r4) |
| stwu r4,-32(r4) |
| mflr r5 |
| stw r5,32+4(r4) |
| stw r1,8(r4) // save caller stack |
| mr r1,r4 |
| stw r2,12(r1) |
| stw r0,16(r1) |
| mfctr r2 |
| stw r2,20(r1) |
| mfcr r2 |
| stw r2,24(r1) |
| mfxer r2 |
| stw r2,28(r1) |
| // do we need to save more registers? |
| bl of_client_interface |
| lwz r4,32+4(r1) |
| mtlr r4 |
| lwz r2,20(r1) |
| mtctr r2 |
| lwz r2,24(r1) |
| mtcr r2 |
| lwz r2,28(r1) |
| mtxer r2 |
| lwz r2,12(r1) |
| lwz r0,16(r1) |
| lwz r1,8(r1) // restore caller stack |
| blr |
| |
| /* rtas glue (must be reloctable) */ |
| GLOBL(of_rtas_start): |
| /* r3 = argument buffer, r4 = of_rtas_start */ |
| /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */ |
| mr r6,r3 |
| lis r3,HA(OSI_SC_MAGIC_R3) |
| addi r3,r3,LO(OSI_SC_MAGIC_R3) |
| lis r4,HA(OSI_SC_MAGIC_R4) |
| addi r4,r4,LO(OSI_SC_MAGIC_R4) |
| li r5,OSI_OF_RTAS |
| sc |
| blr |
| GLOBL(of_rtas_end): |
| |
| |
| /* used in a hack to the newworld calibration */ |
| GLOBL(nw_dec_calibration): |
| .long 0 |
| GLOBL(timer_calib_start): |
| lis r3,HA(nw_dec_calibration) |
| addi r3,r3,LO(nw_dec_calibration) |
| lwz r3,0(r3) |
| blr |
| GLOBL(timer_calib_end): |
| |
| |
| /************************************************************************/ |
| /* vectors */ |
| /************************************************************************/ |
| |
| GLOBL(__vectors): |
| nop // NULL-jmp trap |
| 1: nop // |
| b 1b |
| |
| exception_return: |
| addi r1,r1,16 // pop ABI frame |
| |
| lwz r0,52(r1) |
| mtlr r0 |
| lwz r0,56(r1) |
| mtcr r0 |
| lwz r0,60(r1) |
| mtctr r0 |
| lwz r0,64(r1) |
| mtxer r0 |
| |
| lwz r0,0(r1) // restore r0 |
| lwz r2,8(r1) // restore r2 |
| lwz r3,12(r1) // restore r3 |
| lwz r4,16(r1) |
| lwz r5,20(r1) |
| lwz r6,24(r1) |
| lwz r7,28(r1) |
| lwz r8,32(r1) |
| lwz r9,36(r1) |
| lwz r10,40(r1) |
| lwz r11,44(r1) |
| lwz r12,48(r1) |
| lwz r1,4(r1) // restore r1 |
| rfi |
| |
| trap_error: |
| mflr r3 |
| b unexpected_excep |
| |
| ILLEGAL_VECTOR( 0x100 ) |
| ILLEGAL_VECTOR( 0x200 ) |
| |
| VECTOR( 0x300, "DSI" ): |
| EXCEPTION_PREAMBLE |
| lis r3,HA(dsi_exception) |
| addi r3,r3,LO(dsi_exception) |
| mtctr r3 |
| bctrl |
| b exception_return |
| |
| VECTOR( 0x400, "ISI" ): |
| EXCEPTION_PREAMBLE |
| lis r3,HA(isi_exception) |
| addi r3,r3,LO(isi_exception) |
| mtctr r3 |
| bctrl |
| b exception_return |
| |
| ILLEGAL_VECTOR( 0x500 ) |
| ILLEGAL_VECTOR( 0x600 ) |
| ILLEGAL_VECTOR( 0x700 ) |
| |
| VECTOR( 0x800, "FPU" ): |
| mtsprg1 r3 |
| mfsrr1 r3 |
| ori r3,r3,0x2000 |
| mtsrr1 r3 |
| mfsprg1 r3 |
| rfi |
| |
| ILLEGAL_VECTOR( 0x900 ) |
| ILLEGAL_VECTOR( 0xa00 ) |
| ILLEGAL_VECTOR( 0xb00 ) |
| ILLEGAL_VECTOR( 0xc00 ) |
| ILLEGAL_VECTOR( 0xd00 ) |
| ILLEGAL_VECTOR( 0xe00 ) |
| ILLEGAL_VECTOR( 0xf00 ) |
| ILLEGAL_VECTOR( 0xf20 ) |
| ILLEGAL_VECTOR( 0x1000 ) |
| ILLEGAL_VECTOR( 0x1100 ) |
| ILLEGAL_VECTOR( 0x1200 ) |
| ILLEGAL_VECTOR( 0x1300 ) |
| ILLEGAL_VECTOR( 0x1400 ) |
| ILLEGAL_VECTOR( 0x1500 ) |
| ILLEGAL_VECTOR( 0x1600 ) |
| ILLEGAL_VECTOR( 0x1700 ) |
| |
| GLOBL(__vectors_end): |
| |
| |
| #define CACHE_LINE_SIZE 32 |
| #define LG_CACHE_LINE_SIZE 5 |
| |
| /* flush_icache_range( unsigned long start, unsigned long stop) */ |
| GLOBL(flush_icache_range): |
| li r5,CACHE_LINE_SIZE-1 |
| andc r3,r3,r5 |
| subf r4,r3,r4 |
| add r4,r4,r5 |
| srwi. r4,r4,LG_CACHE_LINE_SIZE |
| beqlr |
| mtctr r4 |
| mr r6,r3 |
| 1: dcbst 0,r3 |
| addi r3,r3,CACHE_LINE_SIZE |
| bdnz 1b |
| sync /* wait for dcbst's to get to ram */ |
| mtctr r4 |
| 2: icbi 0,r6 |
| addi r6,r6,CACHE_LINE_SIZE |
| bdnz 2b |
| sync /* additional sync needed on g4 */ |
| isync |
| blr |