/* * Creation Date: <2001/06/16 21:30:18 samuel> * Time-stamp: <2003/04/04 16:32:06 samuel> * * * * 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