URL
https://opencores.org/ocsvn/ao486/ao486/trunk
Subversion Repositories ao486
[/] [ao486/] [trunk/] [syn/] [components/] [vga/] [software/] [exe_bsp/] [HAL/] [src/] [crt0.S] - Rev 2
Compare with Previous | Blame | View Log
/******************************************************************************* ** License Agreement ** ** Copyright (c) 2006 Altera Corporation, San Jose, California, USA. ** All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), ** to deal in the Software without restriction, including without limitation ** the rights to use, copy, modify, merge, publish, distribute, sublicense, ** and/or sell copies of the Software, and to permit persons to whom the ** Software is furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** ** This agreement shall be governed in all respects by the laws of the State ** of California and by the laws of the United States of America. ** *******************************************************************************/#include "system.h"#include "nios2.h"/* Setup header files to work with assembler code. */#define ALT_ASM_SRC/* Debug logging facility */#include "sys/alt_log_printf.h"/*************************************************************************\| MACROS |\*************************************************************************//** The new build tools explicitly define macros when alt_load()* must be called. The define ALT_LOAD_EXPLICITLY_CONTROLLED tells us that* those macros are controlling if alt_load() needs to be called.*/#ifdef ALT_LOAD_EXPLICITLY_CONTROLLED/* Need to call alt_load() if any of these sections are being copied. */#if defined(ALT_LOAD_COPY_RODATA) || defined(ALT_LOAD_COPY_RWDATA) || defined(ALT_LOAD_COPY_EXCEPTIONS)#define CALL_ALT_LOAD#endif#else /* !ALT_LOAD_EXPLICITLY_CONTROLLED *//** The legacy build tools use the following macros to detect when alt_load()* needs to be called.*/#define __ALT_LOAD_SECTIONS(res, text, rodata, exc) \((res##_BASE != rodata##_BASE) || \(res##_BASE != rwdata##_BASE) || \(res##_BASE != exc##_BASE))#define _ALT_LOAD_SECTIONS(res, text, rodata, exc) \__ALT_LOAD_SECTIONS(res, text, rodata, exc)#define ALT_LOAD_SECTIONS _ALT_LOAD_SECTIONS(ALT_RESET_DEVICE, \ALT_RODATA_DEVICE, \ALT_RWDATA_DEVICE, \ALT_EXCEPTIONS_DEVICE)/* Call alt_load() if there is no bootloader and ALT_LOAD_SECTIONS isn't 0. */#if defined(ALT_NO_BOOTLOADER) && ALT_LOAD_SECTIONS#define CALL_ALT_LOAD#endif#endif /* !ALT_LOAD_EXPLICITLY_CONTROLLED *//** When the legacy build tools define a macro called ALT_NO_BOOTLOADER,* it indicates that initialization code is allowed at the reset address.* The new build tools define a macro called ALT_ALLOW_CODE_AT_RESET for* the same purpose.*/#ifdef ALT_NO_BOOTLOADER#define ALT_ALLOW_CODE_AT_RESET#endif/*************************************************************************\| EXTERNAL REFERENCES |\*************************************************************************//** The entry point for user code is either "main" in hosted mode, or* "alt_main" in standalone mode. These are explicitly referenced here,* to ensure they are built into the executable. This allows the user* to build them into libraries, rather than supplying them in object* files at link time.*/.globl main.globl alt_main/** Create a reference to the software multiply/divide and trap handers,* so that if they are provided, they will appear in the executable.*/#ifndef ALT_NO_INSTRUCTION_EMULATION.globl alt_exception_muldiv#endif#ifdef ALT_TRAP_HANDLER.globl alt_exception_trap#endif/** Linker defined symbols used to initialize bss.*/.globl __bss_start.globl __bss_end/*************************************************************************\| RESET SECTION (.entry) |\*************************************************************************//** This is the reset entry point for Nios II.** At reset, only the cache line which contain the reset vector is* initialized by the hardware. The code within the first cache line* initializes the remainder of the instruction cache.*/.section .entry, "xa".align 5/** Explicitly allow the use of r1 (the assembler temporary register)* within this code. This register is normally reserved for the use of* the assembler.*/.set noat/** Some tools want to know where the reset vector is.* Code isn't always provided at the reset vector but at least the* __reset label always contains the reset vector address because* it is defined at the start of the .entry section.*/.globl __reset.type __reset, @function__reset:/** Initialize the instruction cache if present (i.e. size > 0) and* reset code is allowed unless optimizing for RTL simulation.* RTL simulations can ensure the instruction cache is already initialized* so skipping this loop speeds up RTL simulation.*/#if NIOS2_ICACHE_SIZE > 0 && defined(ALT_ALLOW_CODE_AT_RESET) && !defined(ALT_SIM_OPTIMIZE)/* Assume the instruction cache size is always a power of two. */#if NIOS2_ICACHE_SIZE > 0x8000movhi r2, %hi(NIOS2_ICACHE_SIZE)#elsemovui r2, NIOS2_ICACHE_SIZE#endif0:initi r2addi r2, r2, -NIOS2_ICACHE_LINE_SIZEbgt r2, zero, 0b1:/** The following debug information tells the ISS not to run the loop above* but to perform its actions using faster internal code.*/.pushsection .debug_alt_sim_info.int 1, 1, 0b, 1b.popsection#endif /* Initialize Instruction Cache *//** Jump to the _start entry point in the .text section if reset code* is allowed or if optimizing for RTL simulation.*/#if defined(ALT_ALLOW_CODE_AT_RESET) || defined(ALT_SIM_OPTIMIZE)/* Jump to the _start entry point in the .text section. */movhi r1, %hi(_start)ori r1, r1, %lo(_start)jmp r1.size __reset, . - __reset#endif /* Jump to _start *//** When not using exit, provide an _exit symbol to prevent unresolved* references to _exit from the linker script.*/#ifdef ALT_NO_EXIT.globl _exit_exit:#endif/*************************************************************************\| TEXT SECTION (.text) |\*************************************************************************//** Start of the .text section, and also the code entry point when* the code is executed by a bootloader rather than directly from reset.*/.section .text.align 2.globl _start.type _start, @function_start:/** Initialize the data cache if present (i.e. size > 0) and not* optimizing for RTL simulation.* RTL simulations can ensure the data cache is already initialized* so skipping this loop speeds up RTL simulation.*/#if NIOS2_DCACHE_SIZE > 0 && !defined(ALT_SIM_OPTIMIZE)/* Assume the data cache size is always a power of two. */#if NIOS2_DCACHE_SIZE > 0x8000movhi r2, %hi(NIOS2_DCACHE_SIZE)#elsemovui r2, NIOS2_DCACHE_SIZE#endif0:initd 0(r2)addi r2, r2, -NIOS2_DCACHE_LINE_SIZEbgt r2, zero, 0b1:/** The following debug information tells the ISS not to run the loop above* but to perform its actions using faster internal code.*/.pushsection .debug_alt_sim_info.int 2, 1, 0b, 1b.popsection#endif /* Initialize Data Cache *//* Log that caches have been initialized. */ALT_LOG_PUTS(alt_log_msg_cache)/* Log that the stack pointer is about to be setup. */ALT_LOG_PUTS(alt_log_msg_stackpointer)#if (NIOS2_NUM_OF_SHADOW_REG_SETS == 0)/** Now that the caches are initialized, set up the stack pointer.* The value provided by the linker is assumed to be correctly aligned.*/movhi sp, %hi(__alt_stack_pointer)ori sp, sp, %lo(__alt_stack_pointer)/* Set up the global pointer. */movhi gp, %hi(_gp)ori gp, gp, %lo(_gp)#else /* NIOS2_NUM_OF_SHADOW_REG_SETS > 0 *//** Set up the GP and SP in all shadow register sets.*//** Check current register set number, if CPU resets into a shadow register* set, switch register set to 0 by writing zero to SSTATUS register and* execute an ERET instruction that just jumps to the next PC address* (use the NEXTPC instruction to get this).*/rdctl r2, status/* Get the current register set number (STATUS.CRS). */andi r3, r2, NIOS2_STATUS_CRS_MSK/* Skip switch register set if STATUS.CRS is 0. */beq r3, zero, .Lskip_switch_reg_set.set nobreak/* Current register set is non-zero, set SSTATUS to 0. */mov sstatus, zero/* Get next pc and store in ea. */nextpc ea/* Point to instruction after eret. */addi ea, ea, 8/** Execute ERET instruction that just jumps to the next PC address*/eret.Lskip_switch_reg_set:mov r2, zero/* Reset STATUS register */wrctl status, r2movui r3, NIOS2_NUM_OF_SHADOW_REG_SETS/* Set up the stack pointer in register set 0. */movhi sp, %hi(__alt_stack_pointer)ori sp, sp, %lo(__alt_stack_pointer)/* Set up the global pointer in register set 0. */movhi gp, %hi(_gp)ori gp, gp, %lo(_gp).Lsetup_sp_and_gp_loop:/** Setup GP and SP for shadow register set* from NIOS2_NUM_OF_SHADOW_REG_SETS to 0*//* Skip if number of register sets is 0. */beq r3, zero, .Lno_shadow_register_set/* Add previous register set STATUS.PRS by 1 */movhi r4, 1add r2, r2, r4/* Write STATUS */wrctl status, r2/* Clear r0 in the shadow register set (not done by hardware) */wrprs r0, r0/* Write the GP in previous register set */wrprs gp, gp/* Only write the SP in previous register set* if using the seperate exception stack. For normal case (single stack),* funnel code would read the SP from previous register set.*/#ifdef ALT_INTERRUPT_STACKmovhi et, %hiadj(__alt_interrupt_stack_pointer)addi et, et, %lo(__alt_interrupt_stack_pointer)wrprs sp, et#endif /* ALT_INTERRUPT_STACK *//* Decrease number of register set counter by 1 */addi r3, r3, -1br .Lsetup_sp_and_gp_loop.Lno_shadow_register_set:#endif /* NIOS2_NUM_OF_SHADOW_REG_SETS *//** Clear the BSS if not optimizing for RTL simulation.** This uses the symbols: __bss_start and __bss_end, which are defined* by the linker script. They mark the begining and the end of the bss* region. The linker script guarantees that these values are word aligned.*/#ifndef ALT_SIM_OPTIMIZE/* Log that the BSS is about to be cleared. */ALT_LOG_PUTS(alt_log_msg_bss)movhi r2, %hi(__bss_start)ori r2, r2, %lo(__bss_start)movhi r3, %hi(__bss_end)ori r3, r3, %lo(__bss_end)beq r2, r3, 1f0:stw zero, (r2)addi r2, r2, 4bltu r2, r3, 0b1:/** The following debug information tells the ISS not to run the loop above* but to perform its actions using faster internal code.*/.pushsection .debug_alt_sim_info.int 3, 1, 0b, 1b.popsection#endif /* ALT_SIM_OPTIMIZE *//** The alt_load() facility is normally used when there is no bootloader.* It copies some sections into RAM so it acts like a mini-bootloader.*/#ifdef CALL_ALT_LOAD#ifdef ALT_STACK_CHECK/** If the user has selected stack checking then we need to set up a safe* value in the stack limit register so that the relocation functions* don't think the stack has overflowed (the contents of the rwdata* section aren't defined until alt_load() has been called).*/mov et, zero#endifcall alt_load#endif /* CALL_ALT_LOAD */#ifdef ALT_STACK_CHECK/** Set up the stack limit (if required). The linker has set up the* copy of the variable which is in memory.*/ldw et, %gprel(alt_stack_limit_value)(gp)#endif/* Log that alt_main is about to be called. */ALT_LOG_PUTS(alt_log_msg_alt_main)/* Call the C entry point. It should never return. */call alt_main/* Wait in infinite loop in case alt_main does return. */alt_after_alt_main:br alt_after_alt_main.size _start, . - _start/** Add information about the stack base if stack overflow checking is enabled.*/#ifdef ALT_STACK_CHECK.globl alt_stack_limit_value.section .sdata,"aws",@progbits.align 2.type alt_stack_limit_value, @object.size alt_stack_limit_value, 4alt_stack_limit_value:.long __alt_stack_limit#endif
