/* crt0.S. C design runtime startup file.
|
/* crt0.S. C design runtime startup file.
|
|
|
Copyright (C) 2004, Jacob Bower
|
Copyright (C) 2004, Jacob Bower
|
Copyright (C) 2010, Embecosm Limited
|
Copyright (C) 2010, Embecosm Limited
|
Copyright (C) 2011, ORSoC AB
|
Copyright (C) 2011, ORSoC AB
|
|
|
Contributor Jeremy Bennett
|
Contributor Jeremy Bennett
|
Contributor Julius Baxter
|
Contributor Julius Baxter
|
|
|
This file is part of Newlib.
|
This file is part of Newlib.
|
|
|
The original work by Jacob Bower is provided as-is without any kind of
|
The original work by Jacob Bower is provided as-is without any kind of
|
warranty. Use it at your own risk!
|
warranty. Use it at your own risk!
|
|
|
All subsequent work is bound by version 3 of the GPL as follows.
|
All subsequent work is bound by version 3 of the GPL as follows.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
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
|
under the terms of the GNU General Public License as published by the Free
|
Software Foundation; either version 3 of the License, or (at your option)
|
Software Foundation; either version 3 of the License, or (at your option)
|
any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
more details.
|
more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see . */
|
with this program. If not, see . */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/* This program is commented throughout in a fashion suitable for processing
|
/* This program is commented throughout in a fashion suitable for processing
|
with Doxygen. */
|
with Doxygen. */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
|
|
#include "spr-defs.h"
|
#include "spr-defs.h"
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Macro to load a symbol's address into a register.
|
/*!Macro to load a symbol's address into a register.
|
|
|
@param[in] gpr General purpose register to load address into.
|
@param[in] gpr General purpose register to load address into.
|
@param[in] symbol Name of symbol to load. */
|
@param[in] symbol Name of symbol to load. */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
|
#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
|
.global symbol ; \
|
.global symbol ; \
|
l.movhi gpr, hi(symbol) ; \
|
l.movhi gpr, hi(symbol) ; \
|
l.ori gpr, gpr, lo(symbol)
|
l.ori gpr, gpr, lo(symbol)
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Macro to handle exceptions.
|
/*!Macro to handle exceptions.
|
|
|
Load NPC into r3, EPCR into r4
|
Load NPC into r3, EPCR into r4
|
*/
|
*/
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
// Size of redzone + size of space required to store state
|
// Size of redzone + size of space required to store state
|
// This value must match that in the support library or1k_exception_handler
|
// This value must match that in the support library or1k_exception_handler
|
// function
|
// function
|
#define EXCEPTION_STACK_SIZE (128+128)
|
#define EXCEPTION_STACK_SIZE (128+128)
|
|
|
#define CALL_EXCEPTION_HANDLER \
|
#define CALL_EXCEPTION_HANDLER \
|
l.addi r1, r1, -EXCEPTION_STACK_SIZE; \
|
l.addi r1, r1, -EXCEPTION_STACK_SIZE; \
|
l.sw 4(r1), r3; \
|
l.sw 4(r1), r3; \
|
l.sw 8(r1), r4; \
|
l.sw 8(r1), r4; \
|
l.mfspr r3,r0,SPR_NPC; \
|
l.mfspr r3,r0,SPR_NPC; \
|
l.j or1k_exception_handler; \
|
l.j or1k_exception_handler; \
|
l.mfspr r4,r0,SPR_EPCR_BASE
|
l.mfspr r4,r0,SPR_EPCR_BASE
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Exception vectors */
|
/*!Exception vectors */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
.section .vectors,"ax"
|
.section .vectors,"ax"
|
|
|
/* 0x100: RESET exception */
|
/* 0x100: RESET exception */
|
.org 0x100
|
.org 0x100
|
__reset:
|
__reset:
|
l.movhi r0, 0
|
l.movhi r0, 0
|
l.movhi r1, 0
|
l.movhi r1, 0
|
l.movhi r2, 0
|
l.movhi r2, 0
|
l.movhi r3, 0
|
l.movhi r3, 0
|
l.movhi r4, 0
|
l.movhi r4, 0
|
l.movhi r5, 0
|
l.movhi r5, 0
|
l.movhi r6, 0
|
l.movhi r6, 0
|
l.movhi r7, 0
|
l.movhi r7, 0
|
l.movhi r8, 0
|
l.movhi r8, 0
|
l.movhi r9, 0
|
l.movhi r9, 0
|
l.movhi r10, 0
|
l.movhi r10, 0
|
l.movhi r11, 0
|
l.movhi r11, 0
|
l.movhi r12, 0
|
l.movhi r12, 0
|
l.movhi r13, 0
|
l.movhi r13, 0
|
l.movhi r14, 0
|
l.movhi r14, 0
|
l.movhi r15, 0
|
l.movhi r15, 0
|
l.movhi r16, 0
|
l.movhi r16, 0
|
l.movhi r17, 0
|
l.movhi r17, 0
|
l.movhi r18, 0
|
l.movhi r18, 0
|
l.movhi r19, 0
|
l.movhi r19, 0
|
l.movhi r20, 0
|
l.movhi r20, 0
|
l.movhi r21, 0
|
l.movhi r21, 0
|
l.movhi r22, 0
|
l.movhi r22, 0
|
l.movhi r23, 0
|
l.movhi r23, 0
|
l.movhi r24, 0
|
l.movhi r24, 0
|
l.movhi r25, 0
|
l.movhi r25, 0
|
l.movhi r26, 0
|
l.movhi r26, 0
|
l.movhi r27, 0
|
l.movhi r27, 0
|
l.movhi r28, 0
|
l.movhi r28, 0
|
l.movhi r29, 0
|
l.movhi r29, 0
|
l.movhi r30, 0
|
l.movhi r30, 0
|
l.movhi r31, 0
|
l.movhi r31, 0
|
|
|
/* Clear status register, set supervisor mode */
|
/* Clear status register, set supervisor mode */
|
l.ori r1, r0, SPR_SR_SM
|
l.ori r1, r0, SPR_SR_SM
|
l.mtspr r0, r1, SPR_SR
|
l.mtspr r0, r1, SPR_SR
|
/* Clear timer mode register*/
|
/* Clear timer mode register*/
|
l.mtspr r0, r0, SPR_TTMR
|
l.mtspr r0, r0, SPR_TTMR
|
/* Jump to program initialisation code */
|
/* Jump to program initialisation code */
|
LOAD_SYMBOL_2_GPR(r4, _start)
|
LOAD_SYMBOL_2_GPR(r4, _start)
|
l.jr r4
|
l.jr r4
|
l.nop
|
l.nop
|
|
|
.org 0x200
|
.org 0x200
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x300: Data Page Fault exception */
|
/* 0x300: Data Page Fault exception */
|
.org 0x300
|
.org 0x300
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x400: Insn Page Fault exception */
|
/* 0x400: Insn Page Fault exception */
|
.org 0x400
|
.org 0x400
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x500: Timer exception */
|
/* 0x500: Timer exception */
|
.org 0x500
|
.org 0x500
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x600: Aligment exception */
|
/* 0x600: Aligment exception */
|
.org 0x600
|
.org 0x600
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x700: Illegal insn exception */
|
/* 0x700: Illegal insn exception */
|
.org 0x700
|
.org 0x700
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x800: External interrupt exception */
|
/* 0x800: External interrupt exception */
|
.org 0x800
|
.org 0x800
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0x900: DTLB miss exception */
|
/* 0x900: DTLB miss exception */
|
.org 0x900
|
.org 0x900
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xa00: ITLB miss exception */
|
/* 0xa00: ITLB miss exception */
|
.org 0xa00
|
.org 0xa00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xb00: Range exception */
|
/* 0xb00: Range exception */
|
.org 0xb00
|
.org 0xb00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xc00: Syscall exception */
|
/* 0xc00: Syscall exception */
|
.org 0xc00
|
.org 0xc00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xd00: floating point exception */
|
/* 0xd00: floating point exception */
|
.org 0xd00
|
.org 0xd00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xe00: Trap exception */
|
/* 0xe00: Trap exception */
|
.org 0xe00
|
.org 0xe00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* 0xf00: Reserved exceptions */
|
/* 0xf00: Reserved exceptions */
|
.org 0xf00
|
.org 0xf00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1000
|
.org 0x1000
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1100
|
.org 0x1100
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1200
|
.org 0x1200
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1300
|
.org 0x1300
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1400
|
.org 0x1400
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1500
|
.org 0x1500
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1600
|
.org 0x1600
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1700
|
.org 0x1700
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1800
|
.org 0x1800
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1900
|
.org 0x1900
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1a00
|
.org 0x1a00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1b00
|
.org 0x1b00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1c00
|
.org 0x1c00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1d00
|
.org 0x1d00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1e00
|
.org 0x1e00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
.org 0x1f00
|
.org 0x1f00
|
CALL_EXCEPTION_HANDLER
|
CALL_EXCEPTION_HANDLER
|
|
|
/* Pad to the end */
|
/* Pad to the end */
|
.org 0x1ffc
|
.org 0x1ffc
|
l.nop
|
l.nop
|
|
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/*!Main entry point
|
/*!Main entry point
|
|
|
We initialise the stack and frame pointer first, before we set up the
|
We initialise the stack and frame pointer first, before we set up the
|
caches, since otherwise we'll need to disable the instruction cache when
|
caches, since otherwise we'll need to disable the instruction cache when
|
patching the bus error vector code.
|
patching the bus error vector code.
|
|
|
The remaining tasks are then:
|
The remaining tasks are then:
|
- optionally set up instruction and/or data caches
|
- optionally set up instruction and/or data caches
|
- clear BSS
|
- clear BSS
|
- call global and static constructors
|
- call global and static constructors
|
- set up destructors to be called from exit
|
- set up destructors to be called from exit
|
- jump to the main function
|
- jump to the main function
|
- call exit if the main function ever returns.
|
- call exit if the main function ever returns.
|
- loop forever (should never get here) */
|
- loop forever (should never get here) */
|
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
/* The stack grows down from the top of writable memory. */
|
/* The stack grows down from the top of writable memory. */
|
.section .data
|
.section .data
|
.global stack
|
.global stack
|
stack: .space 4,0
|
stack: .space 4,0
|
|
|
.section .text
|
.section .text
|
.global _start
|
.global _start
|
.type _start,@function
|
.type _start,@function
|
|
|
|
|
/* Following externs from board-specific object passed at link time */
|
/* Following externs from board-specific object passed at link time */
|
.extern _board_mem_base
|
.extern _board_mem_base
|
.extern _board_mem_size
|
.extern _board_mem_size
|
.extern _board_uart_base
|
.extern _board_uart_base
|
|
|
_start:
|
_start:
|
/* Initialise stack and frame pointer (set to same value) */
|
/* Initialise stack and frame pointer (set to same value) */
|
l.movhi r1,hi(_board_mem_base)
|
l.movhi r1,hi(_board_mem_base)
|
l.ori r1,r1,lo(_board_mem_base)
|
l.ori r1,r1,lo(_board_mem_base)
|
l.lwz r1,0(r1)
|
l.lwz r1,0(r1)
|
l.movhi r2,hi(_board_mem_size)
|
l.movhi r2,hi(_board_mem_size)
|
l.ori r2,r2,lo(_board_mem_size)
|
l.ori r2,r2,lo(_board_mem_size)
|
l.lwz r2,0(r2)
|
l.lwz r2,0(r2)
|
l.add r1,r1,r2
|
l.add r1,r1,r2
|
l.or r2,r1,r1
|
l.or r2,r1,r1
|
|
|
/* Store stack address in stack variable */
|
/* Store stack address in stack variable */
|
l.movhi r3,hi(stack)
|
l.movhi r3,hi(stack)
|
l.ori r3,r3,lo(stack)
|
l.ori r3,r3,lo(stack)
|
l.sw 0(r3),r1
|
l.sw 0(r3),r1
|
|
|
/* Initialise cache */
|
/* Initialise cache */
|
/* TODO - potentially make this optional for simulation targets to save
|
/* TODO - potentially make this optional for simulation targets to save
|
time during startup */
|
time during startup */
|
l.jal or1k_cache_init
|
l.jal or1k_cache_init
|
l.nop
|
l.nop
|
|
|
/* Clear BSS */
|
/* Clear BSS */
|
.L10: l.movhi r3,hi(__bss_start)
|
.L10: l.movhi r3,hi(__bss_start)
|
l.ori r3,r3,lo(__bss_start)
|
l.ori r3,r3,lo(__bss_start)
|
l.movhi r4,hi(end)
|
l.movhi r4,hi(end)
|
l.ori r4,r4,lo(end)
|
l.ori r4,r4,lo(end)
|
|
|
.L1: l.sw (0)(r3),r0
|
.L1: l.sw (0)(r3),r0
|
l.sfltu r3,r4
|
l.sfltu r3,r4
|
l.bf .L1
|
l.bf .L1
|
l.addi r3,r3,4 /* Delay slot */
|
l.addi r3,r3,4 /* Delay slot */
|
|
|
/* Reinitialize the reentrancy structure */
|
/* Reinitialize the reentrancy structure */
|
l.jal __impure_init
|
l.jal __impure_init
|
l.nop
|
l.nop
|
|
|
/* Call global and static constructors */
|
/* Call global and static constructors */
|
l.jal __init
|
l.jal __init
|
l.nop
|
l.nop
|
|
|
/* Set up destructors to be called from exit if main ever returns */
|
/* Set up destructors to be called from exit if main ever returns */
|
l.movhi r3,hi(__fini)
|
l.movhi r3,hi(__fini)
|
l.jal atexit
|
l.jal atexit
|
l.ori r3,r3,lo(__fini) /* Delay slot */
|
l.ori r3,r3,lo(__fini) /* Delay slot */
|
|
|
/* Check if UART is to be initialised */
|
/* Check if UART is to be initialised */
|
l.movhi r4,hi(_board_uart_base)
|
l.movhi r4,hi(_board_uart_base)
|
l.ori r4,r4,lo(_board_uart_base)
|
l.ori r4,r4,lo(_board_uart_base)
|
l.lwz r4,0(r4)
|
l.lwz r4,0(r4)
|
l.sfne r4,r0 /* Is base set? If not, no UART */
|
l.sfne r4,r0 /* Is base set? If not, no UART */
|
l.bnf .L2
|
l.bnf .L2
|
l.or r3,r0,r0
|
l.or r3,r0,r0
|
l.jal __uart_init
|
l.jal __uart_init
|
l.nop
|
l.nop
|
|
|
.L2:
|
.L2:
|
/* Jump to main program entry point (argc = argv = envp = 0) */
|
/* Jump to main program entry point (argc = argv = envp = 0) */
|
l.or r3,r0,r0
|
l.or r3,r0,r0
|
l.or r4,r0,r0
|
l.or r4,r0,r0
|
l.jal main
|
l.jal main
|
l.or r5,r0,r0 /* Delay slot */
|
l.or r5,r0,r0 /* Delay slot */
|
|
|
/* If program exits, call exit routine */
|
/* If program exits, call exit routine */
|
l.jal exit
|
l.jal exit
|
l.addi r3,r11,0 /* Delay slot */
|
l.addi r3,r11,0 /* Delay slot */
|
|
|
/* Loop forever */
|
/* Loop forever */
|
.L3: l.j .L3
|
.L3: l.j .L3
|
l.nop
|
l.nop
|
|
|
.size _start, .-_start
|
.size _start, .-_start
|
|
|