Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/or1k/crt0.S')
-rw-r--r--libgloss/or1k/crt0.S600
1 files changed, 0 insertions, 600 deletions
diff --git a/libgloss/or1k/crt0.S b/libgloss/or1k/crt0.S
deleted file mode 100644
index f1753d0d7..000000000
--- a/libgloss/or1k/crt0.S
+++ /dev/null
@@ -1,600 +0,0 @@
-/* crt0.S -- startup file for OpenRISC 1000.
- *
- * Copyright (c) 2011, 2014 Authors
- *
- * Contributor Julius Baxter <juliusbaxter@gmail.com>
- * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de>
- *
- * The authors hereby grant permission to use, copy, modify, distribute,
- * and license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that this
- * notice is included verbatim in any distributions. No written agreement,
- * license, or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their authors
- * and need not follow the licensing terms described here, provided that
- * the new terms are clearly indicated on the first page of each file where
- * they apply.
- */
-
-/* -------------------------------------------------------------------------- */
-/* Coding convention:
- Assembly is hard to read per se, so please follow the following coding
- conventions to keep it consistent and ease reading:
- * internal jump labels start with L, no identation
- * assemble lines have one tab identation
- * attributes (.section, .global, ..) are indented with one tab
- * code is structured using tabs, i.e., use 'l.sw\t0(r1),r1' with a single
- tab. libgloss assumes 8 space tab width, so that might look unstructured
- with tab widths below 6. Nevertheless don't use spaces or two tabs.
- * no space after comma
- * use the defined macros if possible as they reduce errors
- * use OR1K_INST with OR1K_DELAYED(_NOP)
- * OR1K_DELAYED is multiline for better readability, the inner parts are
- indented with another tab.
- * COMMENT! Try to accompy every line with a meaningful comment. If possible
- use pseudo code to describe the code. Also mention intentions and not only
- the obvious things.. */
-/* -------------------------------------------------------------------------- */
-
-#include "include/or1k-asm.h"
-#include "include/or1k-sprs.h"
-
-/* -------------------------------------------------------------------------- */
-// Stack definitions
-/* -------------------------------------------------------------------------- */
-
-// Stacks
-// Memory layout:
-// +--------------------+ <- board_mem_base+board_mem_size/exception_stack_top
-// | exception stack(s) |
-// +--------------------+ <- stack_top
-// | stack(s) |
-// +--------------------+ <- stack_bottom
-// | heap |
-// +--------------------+
-// | text, data, bss.. |
-// +--------------------+
-
-// Reserved stack size
-#define STACK_SIZE 8192
-
-// Reserved stack size for exceptions (can usually be smaller than normal stack)
-#define EXCEPTION_STACK_SIZE 8192
-
-// Size of redzone + size of space required to store state
-// This value must match that in the support library or1k_exception_handler
-// function
-#define EXCEPTION_STACK_FRAME (128+128)
-
- .extern _or1k_stack_top /* points to the next address after the stack */
- .extern _or1k_stack_bottom /* points to the last address in the stack */
- .extern _or1k_exception_stack_top
- .extern _or1k_exception_stack_bottom
-
- .section .data
- .global _or1k_stack_size /* reserved stack size */
- .global _or1k_exception_stack_size
-
-_or1k_stack_size: .word STACK_SIZE
-_or1k_exception_stack_size: .word EXCEPTION_STACK_SIZE
-
-#ifdef __OR1K_MULTICORE__
- .extern _or1k_stack_core
- .extern _or1k_exception_stack_core
-#endif
-
-#define SHADOW_REG(x) (OR1K_SPR_SYS_GPR_BASE + 32 + x)
-
-/* -------------------------------------------------------------------------- */
-/*!Macro to handle exceptions.
-
- Load NPC into r3, EPCR into r4
- */
-/* -------------------------------------------------------------------------- */
-
-#define GPR_BUF_OFFSET(x) (x << 2)
-
-#ifndef __OR1K_MULTICORE__
-#define CALL_EXCEPTION_HANDLER \
- /* store current stack pointer to address 4 */ \
- l.sw 0x4(r0),r1; \
- /* Load top of the exception stack */ \
- l.movhi r1,hi(_or1k_exception_stack_top); \
- l.ori r1,r1,lo(_or1k_exception_stack_top); \
- l.lwz r1,0(r1); \
- /* Reserve red zone and context space */ \
- l.addi r1,r1,-EXCEPTION_STACK_FRAME; \
- /* Store GPR3 in context */ \
- l.sw GPR_BUF_OFFSET(3)(r1),r3; \
- /* Load back software's stack pointer */ \
- l.lwz r3,0x4(r0); \
- /* Store this in the context */ \
- l.sw GPR_BUF_OFFSET(1)(r1),r3; \
- /* Store GPR4 in the context */ \
- l.sw GPR_BUF_OFFSET(4)(r1),r4; \
- /* Copy the current program counter as first */ \
- /* argument for the exception handler. This */ \
- /* is then used to determine the exception. */ \
- l.mfspr r3,r0,OR1K_SPR_SYS_NPC_ADDR; \
- OR1K_DELAYED( \
- /* Copy program counter of exception as */ \
- /* second argument to the exception handler */ \
- OR1K_INST(l.mfspr r4,r0,OR1K_SPR_SYS_EPCR_BASE),\
- /* Jump to exception handler. This will rfe */ \
- OR1K_INST(l.j _or1k_exception_handler) \
- )
-#else
-#define CALL_EXCEPTION_HANDLER \
- /* store current stack pointer to shadow reg */ \
- l.mtspr r0,r1,SHADOW_REG(1); \
- /* store current GPR3 as we need it */ \
- l.mtspr r0,r3,SHADOW_REG(2); \
- /* Load pointer to exception stack array */ \
- l.movhi r1,hi(_or1k_exception_stack_core); \
- l.ori r1,r1,lo(_or1k_exception_stack_core); \
- l.lwz r1,0(r1); \
- /* Get core id */ \
- l.mfspr r3,r0,OR1K_SPR_SYS_COREID_ADDR; \
- /* Calculate offset in array */ \
- l.slli r3,r3,2; \
- /* Load value from array to stack pointer */ \
- l.add r1,r1,r3; \
- l.lwz r1,0(r1); \
- /* Reserve red zone and context space */ \
- l.addi r1,r1,-EXCEPTION_STACK_FRAME; \
- /* Load back software's stack pointer */ \
- l.mfspr r3,r0,SHADOW_REG(1); \
- /* Store this in the context */ \
- l.sw GPR_BUF_OFFSET(1)(r1),r3; \
- /* Load back GPR3 */ \
- l.mfspr r3,r0,SHADOW_REG(2); \
- /* Store this in the context */ \
- l.sw GPR_BUF_OFFSET(3)(r1),r3; \
- /* Store GPR4 in the context */ \
- l.sw GPR_BUF_OFFSET(4)(r1),r4; \
- /* Copy the current program counter as first */ \
- /* argument for the exception handler. This */ \
- /* is then used to determine the exception. */ \
- l.mfspr r3,r0,OR1K_SPR_SYS_NPC_ADDR; \
- OR1K_DELAYED( \
- /* Copy program counter of exception as */ \
- /* second argument to the exception handler */ \
- OR1K_INST(l.mfspr r4,r0,OR1K_SPR_SYS_EPCR_BASE),\
- /* Jump to exception handler. This will rfe */ \
- OR1K_INST(l.j _or1k_exception_handler) \
- )
-#endif
-
-/* -------------------------------------------------------------------------- */
-/*!Exception vectors */
-/* -------------------------------------------------------------------------- */
- .section .vectors,"ax"
-
- /* 0x100: RESET exception */
- .org 0x100
-_or1k_reset:
- l.movhi r0,0
-#ifdef __OR1K_MULTICORE__
- // This is a hack that relies on the fact, that all cores start at the
- // same time and they are similarily fast
- l.sw 0x4(r0),r0
- // Similarly, we use address 8 to signal how many cores have exit'ed
- l.sw 0x8(r0),r0
-#endif
- l.movhi r1,0
- l.movhi r2,0
- l.movhi r3,0
- l.movhi r4,0
- l.movhi r5,0
- l.movhi r6,0
- l.movhi r7,0
- l.movhi r8,0
- l.movhi r9,0
- l.movhi r10,0
- l.movhi r11,0
- l.movhi r12,0
- l.movhi r13,0
- l.movhi r14,0
- l.movhi r15,0
- l.movhi r16,0
- l.movhi r17,0
- l.movhi r18,0
- l.movhi r19,0
- l.movhi r20,0
- l.movhi r21,0
- l.movhi r22,0
- l.movhi r23,0
- l.movhi r24,0
- l.movhi r25,0
- l.movhi r26,0
- l.movhi r27,0
- l.movhi r28,0
- l.movhi r29,0
- l.movhi r30,0
- l.movhi r31,0
-
- /* Clear status register, set supervisor mode */
- l.ori r1,r0,OR1K_SPR_SYS_SR_SM_MASK
- l.mtspr r0,r1,OR1K_SPR_SYS_SR_ADDR
- /* Clear timer mode register*/
- l.mtspr r0,r0,OR1K_SPR_TICK_TTMR_ADDR
- /* Jump to program initialisation code */
- LOAD_SYMBOL_2_GPR(r4, _or1k_start)
- OR1K_DELAYED_NOP(OR1K_INST(l.jr r4))
-
- .org 0x200
- CALL_EXCEPTION_HANDLER
-
- /* 0x300: Data Page Fault exception */
- .org 0x300
- CALL_EXCEPTION_HANDLER
-
- /* 0x400: Insn Page Fault exception */
- .org 0x400
- CALL_EXCEPTION_HANDLER
-
- /* 0x500: Timer exception */
- .org 0x500
- CALL_EXCEPTION_HANDLER
-
- /* 0x600: Aligment exception */
- .org 0x600
- CALL_EXCEPTION_HANDLER
-
- /* 0x700: Illegal insn exception */
- .org 0x700
- CALL_EXCEPTION_HANDLER
-
- /* 0x800: External interrupt exception */
- .org 0x800
- CALL_EXCEPTION_HANDLER
-
- /* 0x900: DTLB miss exception */
- .org 0x900
- CALL_EXCEPTION_HANDLER
-
- /* 0xa00: ITLB miss exception */
- .org 0xa00
- CALL_EXCEPTION_HANDLER
-
- /* 0xb00: Range exception */
- .org 0xb00
- CALL_EXCEPTION_HANDLER
-
- /* 0xc00: Syscall exception */
- .org 0xc00
- CALL_EXCEPTION_HANDLER
-
- /* 0xd00: Floating point exception */
- .org 0xd00
- CALL_EXCEPTION_HANDLER
-
- /* 0xe00: Trap exception */
- .org 0xe00
- CALL_EXCEPTION_HANDLER
-
- /* 0xf00: Reserved exceptions */
- .org 0xf00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1000
- CALL_EXCEPTION_HANDLER
-
- .org 0x1100
- CALL_EXCEPTION_HANDLER
-
- .org 0x1200
- CALL_EXCEPTION_HANDLER
-
- .org 0x1300
- CALL_EXCEPTION_HANDLER
-
- .org 0x1400
- CALL_EXCEPTION_HANDLER
-
- .org 0x1500
- CALL_EXCEPTION_HANDLER
-
- .org 0x1600
- CALL_EXCEPTION_HANDLER
-
- .org 0x1700
- CALL_EXCEPTION_HANDLER
-
- .org 0x1800
- CALL_EXCEPTION_HANDLER
-
- .org 0x1900
- CALL_EXCEPTION_HANDLER
-
- .org 0x1a00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1b00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1c00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1d00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1e00
- CALL_EXCEPTION_HANDLER
-
- .org 0x1f00
- CALL_EXCEPTION_HANDLER
-
- /* Pad to the end */
- .org 0x1ffc
- l.nop
-
-/* -------------------------------------------------------------------------- */
-/*!Main entry point
-
- This is the initialization code of the library. It performs these steps:
-
- * Call early board initialization:
- Before anything happened, the board support may do some very early
- initialization. This is at maximum some very basic stuff that would
- otherwise prevent the following code from functioning. Other initialization
- of peripherals etc. is done later (before calling main).
- See the description below and README.board for details.
-
- * Initialize the stacks:
- Two stacks are configured: The system stack is used by the software and
- the exception stack is used when an exception occurs. We added this as
- this should be flexible with respect to the usage of virtual memory.
-
- * Activate the caches:
- If available the caches are initiliazed and activated.
-
- * Clear BSS:
- The BSS are essentially the uninitialized C variables. They are set to 0
- by default. This is performed by this function.
-
- * Initialize the impure data structure:
- Similarly, we need two library contexts, one for the normal software and
- one that is used during exceptions. The impure data structure holds
- the context information of the library. The called C function will setup
- both data structures. There is furthermore a pointer to the currently
- active impure data structure, which is initially set to the normal one.
-
- * Initialize or1k support library reentrant data structures
-
- * Initialize constructors:
- Call the static and global constructors
-
- * Set up destructors to call from exit
- The library will call the function set via atexit() during exit(). We set
- it to call the _fini function which performs destruction.
-
- * Call board initialization:
- The board initialization can perform board specific initializations such as
- configuring peripherals etc.
-
- * Jump to main
- Call main with argc = 0 and *argv[] = 0
-
- * Call exit after main returns
- Now we call exit()
-
- * Loop forever
- We are dead.
-*/
-
-/* -------------------------------------------------------------------------- */
- .section .text
-
- /* Following externs from board-specific object passed at link time */
- .extern _or1k_board_mem_base
- .extern _or1k_board_mem_size
- .extern _or1k_board_uart_base
-
- /* The early board initialization may for example read the memory size and
- set the mem_base and mem_size or do some preliminary board
- initialization. As we do not have a stack at this time, the function may
- not use the stack (and therefore be a or call a C function. But it can
- safely use all registers.
-
- We define a default implementation, which allows board files in C. As
- described above, this can only be used in assembly (board_*.S) as at
- the early stage not stack is available. A board that needs early
- initialization can overwrite the function with .global _board_init_early.
-
- Recommendation: Only use when you really need it! */
- .weak _or1k_board_init_early
-_or1k_board_init_early:
- OR1K_DELAYED_NOP(OR1K_INST(l.jr r9))
-
- /* The board initialization is then called after the C library and UART
- are initialized. It can then be used to configure UART or other
- devices before the actual main function is called. */
- .extern _or1k_board_init
-
- .global _or1k_start
- .type _or1k_start,@function
-_or1k_start:
- /* It is good to initialize and enable the caches before we do anything,
- otherwise the cores will continuously access the bus during the wait
- time for the boot barrier (0x4).
- Fortunately or1k_cache_init does not need a stack */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_cache_init))
-
-#ifdef __OR1K_MULTICORE__
- // All but core 0 have to wait
- l.mfspr r1, r0, OR1K_SPR_SYS_COREID_ADDR
- l.sfeq r1, r0
- OR1K_DELAYED_NOP(OR1K_INST(l.bf .Lcore0))
-.Lspin:
- /* r1 will be used by the other cores to check for the boot variable
- Check if r1 is still zero, core 0 will set it to 1 once it booted
- As the cache is already turned on, this will not create traffic on
- the bus, but the change is snooped by cache coherency then */
- l.lwz r1,0x4(r0)
- l.sfeq r1, r0
- OR1K_DELAYED_NOP(OR1K_INST(l.bf .Lspin))
-
- /* Initialize core i stack */
- // _or1k_stack_core is the array of stack pointers
- LOAD_SYMBOL_2_GPR(r2,_or1k_stack_core)
- // Load the base address
- l.lwz r2,0(r2)
- // Generate offset in array
- l.mfspr r1,r0,OR1K_SPR_SYS_COREID_ADDR
- l.slli r1,r1,2
- // Add to array base
- l.add r2,r2,r1
- // Load pointer to the stack top and set frame pointer
- l.lwz r1,0(r2)
- l.or r2,r1,r1
-
- // The slave cores are done, jump to main part
- OR1K_DELAYED_NOP(OR1K_INST(l.j .Linit_done));
-
- /* Only core 0 executes the initialization code */
-.Lcore0:
-#endif
- /* Call early board initialization */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_board_init_early))
-
- /* Clear BSS */
-.Lclear_bss:
- LOAD_SYMBOL_2_GPR(r3,__bss_start)
- LOAD_SYMBOL_2_GPR(r4,end)
-
-.Lclear_bss_loop:
- l.sw (0)(r3),r0
- l.sfltu r3,r4
- OR1K_DELAYED(
- OR1K_INST(l.addi r3,r3,4),
- OR1K_INST(l.bf .Lclear_bss_loop)
- )
-
- /* Initialise stack and frame pointer (set to same value) */
- LOAD_SYMBOL_2_GPR(r1,_or1k_board_mem_base)
- l.lwz r1,0(r1)
- LOAD_SYMBOL_2_GPR(r2,_or1k_board_mem_size)
- l.lwz r2,0(r2)
- l.add r1,r1,r2
-
- /* Store exception stack top address */
- LOAD_SYMBOL_2_GPR(r3,_or1k_exception_stack_top)
- l.sw 0(r3),r1
-
- /* Store exception stack bottom address */
- // calculate bottom address
- // r3 = *exception stack size
- LOAD_SYMBOL_2_GPR(r3,_or1k_exception_stack_size)
- // r3 = exception stack size
- l.lwz r3,0(r3)
-#ifdef __OR1K_MULTICORE__
- l.mfspr r4,r0,OR1K_SPR_SYS_NUMCORES_ADDR
- l.mul r3,r4,r3
-#endif
- // r4 = exception stack top - exception stack size = exception stack bottom
- l.sub r4,r1,r3
- // r5 = *exception stack bottom
- LOAD_SYMBOL_2_GPR(r5,_or1k_exception_stack_bottom)
- // store
- l.sw 0(r5),r4
-
- // Move stack pointer accordingly
- l.or r1,r0,r4
- l.or r2,r1,r1
-
- /* Store stack top address */
- LOAD_SYMBOL_2_GPR(r3,_or1k_stack_top)
- l.sw 0(r3),r1
-
- /* Store stack bottom address */
- // calculate bottom address
- // r3 = stack size
- LOAD_SYMBOL_2_GPR(r3,_or1k_stack_size)
- l.lwz r3,0(r3)
-#ifdef __OR1K_MULTICORE__
- l.mfspr r4, r0, OR1K_SPR_SYS_NUMCORES_ADDR
- l.mul r3, r4, r3
-#endif
- // r4 = stack top - stack size = stack bottom
- // -> stack bottom
- l.sub r4,r1,r3
- // r5 = *exception stack bottom
- LOAD_SYMBOL_2_GPR(r5,_or1k_stack_bottom)
- // store to variable
- l.sw 0(r5),r4
-
- /* Reinitialize the or1k support library */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_init))
-
- /* Reinitialize the reentrancy structure */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_libc_impure_init))
-
- /* Call global and static constructors */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _init))
-
- /* Set up destructors to be called from exit if main ever returns */
- l.movhi r3,hi(_fini)
- OR1K_DELAYED(
- OR1K_INST(l.ori r3,r3,lo(_fini)),
- OR1K_INST(l.jal atexit)
- )
-
- /* Check if UART is to be initialised */
- LOAD_SYMBOL_2_GPR(r4,_or1k_board_uart_base)
- l.lwz r4,0(r4)
- /* Is base set? If not, no UART */
- l.sfne r4,r0
- l.bnf .Lskip_uart
- l.or r3,r0,r0
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_uart_init))
-
-.Lskip_uart:
- /* Board initialization */
- OR1K_DELAYED_NOP(OR1K_INST(l.jal _or1k_board_init))
-
-#ifdef __OR1K_MULTICORE__
- // Start other cores
- l.ori r3, r0, 1
- l.sw 0x4(r0), r3
-#endif
-
-.Linit_done:
- /* Jump to main program entry point (argc = argv = envp = 0) */
- l.or r3,r0,r0
- l.or r4,r0,r0
- OR1K_DELAYED(
- OR1K_INST(l.or r5,r0,r0),
- OR1K_INST(l.jal main)
- )
-
-#ifdef __OR1K_MULTICORE__
-.incrementexit:
- /* Atomically increment number of finished cores */
- l.lwa r3,0x8(r0)
- l.addi r3,r3,1
- l.swa 0x8(r0),r3
- OR1K_DELAYED_NOP(OR1K_INST(l.bnf .incrementexit));
- /* Compare to number of cores in this cluster */
- l.mfspr r4,r0, OR1K_SPR_SYS_NUMCORES_ADDR
- /* Compare to number of finished tasks */
- l.sfeq r3,r4
- /* Last core needs to desctruct library etc. */
- OR1K_DELAYED_NOP(OR1K_INST(l.bf .exitcorelast));
- OR1K_DELAYED(
- OR1K_INST(l.addi r3,r11,0),
- OR1K_INST(l.jal _exit)
- )
-.exitcorelast:
-#endif
- /* If program exits, call exit routine */
- OR1K_DELAYED(
- OR1K_INST(l.addi r3,r11,0),
- OR1K_INST(l.jal exit)
- )
-
- /* Loop forever */
-.Lloop_forever:
- OR1K_DELAYED_NOP(OR1K_INST(l.j .Lloop_forever))
-
- .size _or1k_start,.-_or1k_start