sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\euser\epoc\arm\uc_exe.cia sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: // Include this to get imports from User (i.e. User::Invariant and User::HandleException). sl@0: // This sets VISIBILITY to DEFAULT for BPABI builds. sl@0: #include sl@0: sl@0: extern "C" { sl@0: sl@0: void _xxxx_call_user_invariant(); sl@0: void _xxxx_call_user_handle_exception(void *); sl@0: sl@0: extern void RunThread(TBool aNotFirst, SThreadCreateInfo& aInfo); sl@0: sl@0: // NOTE: This MUST be the first function in this module sl@0: __NAKED__ TInt _E32Startup() sl@0: { sl@0: // Process entry point sl@0: // R4 = entry reason sl@0: // SP points to information block sl@0: EKA2_ENTRY_POINT_VERSION_IDENTIFIER; // DUMMY INSTRUCTION TO INDICATE EKA2 ENTRY POINT sl@0: asm("cmp r4, #%a0" : : "i" ((TInt)KModuleEntryReasonThreadInit) ); sl@0: asm("b 1f "); // branch over space for unique ID sl@0: sl@0: asm(".word 0 "); // loader will replace with code seg unique ID sl@0: // for RAM-loaded code segment sl@0: // MUST BE AT OFFSET 12 FROM ENTRY POINT sl@0: sl@0: asm("1: "); sl@0: asm("movls r0, r4 "); // r0 = aNotFirst sl@0: asm("movls r1, sp "); // r1 -> parameter block sl@0: asm("bls RunThread "); // process or thread init sl@0: asm("cmp r4, #%a0" : : "i" ((TInt)KModuleEntryReasonException) ); sl@0: // asm("bne " CSM_ZN4User9InvariantEv ); // invalid entry reason sl@0: asm("bne _xxxx_call_user_invariant " ); // invalid entry reason sl@0: sl@0: // exception entry sl@0: // NOTE: THUMB only works on ARMv5 and above sl@0: asm("mov r0, sp "); // r0->parameter block sl@0: asm("ldr r4, [sp, #16]"); // r4 = saved CPSR sl@0: asm("tst r4, #0x20 "); // test for THUMB sl@0: asm("ldrne r1, [sp, #80] "); // r1 = saved return addr sl@0: asm("orrne r1, r1, #1 "); sl@0: asm("strne r1, [sp, #80] "); // if THUMB, set bit 0 of return addr sl@0: sl@0: asm("mov r11, sp "); // save stack pointer sl@0: sl@0: // The frame starts 84 bytes (up) from r11 i.e. CFA is r11 + 84 sl@0: __EH_FRAME_ADDRESS(r11, 84) sl@0: // we can only restore callee-save values, but that's what we want if we 'leave' sl@0: // saved link is -8 bytes from CFA (= r11 + 0x24 + 0x20 + 0x8) sl@0: __EH_FRAME_SAVE1(lr, -8) sl@0: sl@0: // the other callee saves start at -48 from CFA (= r11 + 0x24) sl@0: #if 0 sl@0: // would like to say this sl@0: __EH_FRAME_SAVE1(r4-r11, -48) sl@0: // but the macro expansion gives rise to odd code so we do what follows sl@0: #endif sl@0: #ifdef __ARMCC__ sl@0: FRAME SAVE {r4-r11}, -48 sl@0: #endif sl@0: sl@0: asm("bic sp, sp, #4 "); // align stack to 8 byte boundary sl@0: // asm("bl " CSM_ZN4User15HandleExceptionEPv ); sl@0: asm("bl _xxxx_call_user_handle_exception "); sl@0: asm("add sp, r11, #16 "); // skip exc type, exc code, FAR, FSR sl@0: asm("ldr r4, [sp], #4 "); // r4 = saved CPSR sl@0: asm("bic r4, r4, #0x20 "); // clear THUMB bit sl@0: asm("msr cpsr, r4 "); // restore flags sl@0: asm("ldmia sp, {r0-r15} "); // restore r0-r15 sl@0: sl@0: #ifdef __ARMCC__ sl@0: #ifdef __SUPPORT_CPP_EXCEPTIONS__ sl@0: sl@0: sl@0: /* It is possible no functions included in the image require sl@0: * a handler table. Therefore make only a weak reference to sl@0: * the handler table base symbol, which may be absent. sl@0: */ sl@0: extern |.ARM.exidx$$Base|; sl@0: extern |.ARM.exidx$$Limit|; sl@0: extern |.ARM.extab$$Base| [WEAK]; sl@0: extern |Image$$ER_RO$$Base|; sl@0: extern |Image$$ER_RO$$Limit|; sl@0: export |Symbian$$CPP$$Exception$$Descriptor|; sl@0: sl@0: |Symbian$$CPP$$Exception$$Descriptor| sl@0: #ifdef __LEAVE_EQUALS_THROW__ sl@0: |Symbian$$eit_base| dcd |.ARM.exidx$$Base|; /* index table base */ sl@0: |Symbian$$eit_limit| dcd |.ARM.exidx$$Limit| ; /* index table limit */ sl@0: #endif sl@0: #if __ARMCC_VERSION > 220000 sl@0: |Symbian$$code_seg_base| dcd |Image$$ER_RO$$Base| + 1 ; /* RO segment base + mark as ehabi v2 */ sl@0: |Symbian$$code_seg_limit| dcd |Image$$ER_RO$$Limit| ;/* RO segment limit */ sl@0: |Symbian$$reserved| dcd 0 ; /* reserved for future use */ sl@0: #else sl@0: |Symbian$$code_seg_base| dcd |Image$$ER_RO$$Base| ; /* RO segment base */ sl@0: |Symbian$$code_seg_limit| dcd |Image$$ER_RO$$Limit| ;/* RO segment limit */ sl@0: #endif sl@0: sl@0: #endif sl@0: #endif sl@0: sl@0: } sl@0: void _xxxx_call_user_invariant() { User::Invariant(); } sl@0: void _xxxx_call_user_handle_exception(void * arg) { User::HandleException(arg); } sl@0: sl@0: } sl@0: