This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, OR1K] crt0


Hi again,

this patch contains the basic build files for ligbloss/or1k and the C runtime. It has some external dependencies that are fulfilled by libor1k and the board files that will follow.

Bye,
Stefan
commit eb15b2efba4efcead63c0b5b5289fc0dcf45307b
Author: Stefan Wallentowitz <stefan.wallentowitz@tum.de>
Date:   Thu Dec 11 16:43:15 2014 +0100

    OR1K: C runtime
    
    This requires the initialization functions and board functions as
    provided by upcoming commits.
    
    libgloss/Changelog:
    	* configure.in: Add or1k/or1knd
    	* or1k/Makefile.in: New file
    	* or1k/configure.in: New file
    	* or1k/crt0.S: New file
    	* or1k/include/or1k-asm.h: New file

diff --git a/libgloss/README b/libgloss/README
index e2a420f..1141841 100644
--- a/libgloss/README
+++ b/libgloss/README
@@ -7,4 +7,5 @@ mep	- Toshiba Media Processor.
 pa	- WinBond and Oki boards with a PA.
 mips	- R3000 support. Array Tech LSI33k based RAID disk controller.
 lm32    - Lattice Mico32 simulator.
-epiphany - Adapteva Epiphany multicore processor.
\ No newline at end of file
+epiphany - Adapteva Epiphany multicore processor.
+or1k	- OpenRISC 1000 processor.
\ No newline at end of file
diff --git a/libgloss/configure.in b/libgloss/configure.in
index 93cc369..74d4fd6 100644
--- a/libgloss/configure.in
+++ b/libgloss/configure.in
@@ -159,6 +159,9 @@ case "${target}" in
   iq2000-*-*)
 	AC_CONFIG_SUBDIRS([iq2000])
 	;;
+  or1k-*-* | or1knd-*-* )
+	AC_CONFIG_SUBDIRS([or1k])
+	;;
 esac
 
 dnl For now, don't bother configuring testsuite
diff --git a/libgloss/or1k/Makefile.in b/libgloss/or1k/Makefile.in
new file mode 100644
index 0000000..cf6197a
--- /dev/null
+++ b/libgloss/or1k/Makefile.in
@@ -0,0 +1,100 @@
+# Copyright (c) 1998 Cygnus Support
+#
+# 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.
+
+DESTDIR =
+VPATH = @srcdir@
+srcdir = @srcdir@
+objdir = .
+srcroot = $(srcdir)/../..
+objroot = $(objdir)/../..
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+
+bindir = @bindir@
+libdir = @libdir@
+includedir = @includedir@
+tooldir = $(exec_prefix)/$(target_alias)
+
+# Multilib support variables.
+# TOP is used instead of MULTI{BUILD,SRC}TOP.
+MULTIDIRS =
+MULTISUBDIR =
+MULTIDO = true
+MULTICLEAN = true
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+SHELL =	/bin/sh
+
+CC = @CC@
+AS = @AS@
+AR = @AR@
+LD = @LD@
+RANLIB = @RANLIB@
+
+OBJDUMP = `if [ -f ${objroot}/../binutils/objdump ] ; \
+	then echo ${objroot}/../binutils/objdump ; \
+	else t='$(program_transform_name)'; echo objdump | sed -e $$t ; fi`
+OBJCOPY = `if [ -f ${objroot}/../binutils/objcopy ] ; \
+	then echo ${objroot}/../binutils/objcopy ; \
+	else t='$(program_transform_name)'; echo objcopy | sed -e $$t ; fi`
+
+GCC_LDFLAGS = `if [ -d ${objroot}/../gcc ] ; \
+	then echo -L${objroot}/../gcc ; fi`
+
+OUTPUTS = crt0.o
+
+# Host specific makefile fragment comes in here.
+@host_makefile_frag@
+
+
+all: ${OUTPUTS}
+
+#
+# here's where we build the library for each target
+#
+
+doc:
+
+clean mostlyclean:
+	rm -f $(OUTPUTS) $(BOARD_LIBS) *.i *~ *.o *-test *.srec *.dis *.map *.x
+
+distclean maintainer-clean realclean: clean
+	rm -f Makefile config.status $(OUTPUTS)
+
+.PHONY: install info install-info clean-info
+install:
+	@for outputs in ${OUTPUTS}; do\
+	 mkdir -p $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}; \
+	 $(INSTALL_DATA) $${outputs} $(DESTDIR)$(tooldir)/lib${MULTISUBDIR}; \
+	done
+	$(INSTALL_DATA) ${srcdir}/include/or1k-support.h $(DESTDIR)$(tooldir)/include/
+	$(INSTALL_DATA) ${srcdir}/include/or1k-sprs.h $(DESTDIR)$(tooldir)/include/
+	$(INSTALL_DATA) ${srcdir}/include/or1k-asm.h $(DESTDIR)$(tooldir)/include/
+	$(INSTALL_DATA) ${srcdir}/include/or1k-nop.h $(DESTDIR)$(tooldir)/include/
+
+info:
+install-info:
+clean-info:
+
+Makefile: Makefile.in config.status @host_makefile_frag_path@
+	$(SHELL) config.status
+
+config.status: configure
+	$(SHELL) config.status --recheck
diff --git a/libgloss/or1k/configure.in b/libgloss/or1k/configure.in
new file mode 100644
index 0000000..5337a4d
--- /dev/null
+++ b/libgloss/or1k/configure.in
@@ -0,0 +1,81 @@
+# Makefile for libgloss/or1k
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.                                               */
+
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ(2.59)
+AC_INIT(libor1k,0.0.1)
+
+# No shared libraries allowed
+if test "${enable_shared}" = "yes" ; then
+    echo "Shared libraries not supported for cross compiling, ignored"
+fi
+
+# Where are the auxillary tools (confg.sub etc)?
+if test "$srcdir" = "." ; then
+  if test "${with_target_subdir}" != "." ; then
+    libgloss_topdir="${srcdir}/${with_multisrctop}../../.."
+  else
+    libgloss_topdir="${srcdir}/${with_multisrctop}../.."
+  fi
+else
+  libgloss_topdir="${srcdir}/../.."
+fi
+AC_CONFIG_AUX_DIR($libgloss_topdir)
+
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+AC_PROG_INSTALL
+
+AC_DEFINE(HAVE_GNU_LD, 1, [Using GNU ld])
+
+# We always use ELF, define various useful associated things.
+AC_DEFINE(HAVE_ELF, 1, [Using ELF format])
+
+# Standard stuff copied from libnosys. For this we'll need to an aclocal.m4
+LIB_AC_PROG_CC
+AS=${AS-as}
+AC_SUBST(AS)
+AR=${AR-ar}
+AC_SUBST(AR)
+LD=${LD-ld}
+AC_SUBST(LD)
+AC_PROG_RANLIB
+LIB_AM_PROG_AS
+
+host_makefile_frag=${srcdir}/../config/default.mh
+target_makefile_frag=${srcdir}/../config/default.mt
+
+dnl We have to assign the same value to other variables because autoconf
+dnl doesn't provide a mechanism to substitute a replacement keyword with
+dnl arbitrary data or pathnames.
+dnl
+host_makefile_frag_path=$host_makefile_frag
+AC_SUBST(host_makefile_frag_path)
+AC_SUBST_FILE(host_makefile_frag)
+target_makefile_frag_path=$target_makefile_frag
+AC_SUBST(target_makefile_frag_path)
+AC_SUBST_FILE(target_makefile_frag)
+
+AC_CONFIG_FILES(Makefile,
+. ${libgloss_topdir}/config-ml.in,
+srcdir=${srcdir}
+target=${target}
+with_multisubdir=${with_multisubdir}
+ac_configure_args="${ac_configure_args} --enable-multilib"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+libgloss_topdir=${libgloss_topdir}
+)
+AC_OUTPUT
\ No newline at end of file
diff --git a/libgloss/or1k/crt0.S b/libgloss/or1k/crt0.S
new file mode 100644
index 0000000..f1753d0
--- /dev/null
+++ b/libgloss/or1k/crt0.S
@@ -0,0 +1,600 @@
+/* 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
diff --git a/libgloss/or1k/include/or1k-asm.h b/libgloss/or1k/include/or1k-asm.h
new file mode 100644
index 0000000..c218c64
--- /dev/null
+++ b/libgloss/or1k/include/or1k-asm.h
@@ -0,0 +1,83 @@
+/* or1k-asm.h -- OR1K assembly helper macros
+
+   Copyright (c) 2014 OpenRISC Project Maintainers
+   Copyright (C) 2012-2014 Peter Gavin <pgavin@gmail.com>
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following condition
+   is met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+   OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   */
+
+#ifndef OR1K_ASM_H
+#define OR1K_ASM_H
+
+/* The purpose of the OR1K_INST macro is simply to protect the commas
+   embedded within an instruction from the C preprocessor.  An entire
+   instruction can be safely embedded within its arguments, including
+   an arbitrary number of commas, and it will be reproduced
+   exactly. */
+#define OR1K_INST(...) __VA_ARGS__
+
+/* OR1K_DELAYED takes two arguments which must be instructions.  They
+   should be wrapped in OR1K_INST if the instructions require commas.
+   The second argument should be a jump or branch instruction.  If we
+   are assembling the code in delay-slot mode (e.g., for the standard
+   OR1K) the first instruction will be emitted in the delay slot of
+   the second instruction.  In no-delay-slot mode they will be emitted
+   in order.  If we are using compat-delay mode, they will be emitted
+   in order, but an l.nop instruction will be emitted immediately
+   after. */
+
+/* OR1K_DELAYED_NOP takes a single argument, which should be a
+   branch/jump instruction.  In delay-slot or compat-delay modes, the
+   instruction will be emitted with an l.nop in its delay slot. In
+   no-delay mode, the instruction will be emitted by itself. */
+
+#if defined(__OR1K_NODELAY__)
+
+#define OR1K_DELAYED(a, b) a; b
+#define OR1K_DELAYED_NOP(a) a
+
+/* Go ahead and emit the .nodelay directive when in no-delay mode, so
+   that the flags are appropriately set in the binary. */
+.nodelay
+
+#elif defined(__OR1K_DELAY__)
+
+#define OR1K_DELAYED(a, b) b; a
+#define OR1K_DELAYED_NOP(a) a; l.nop
+
+#elif defined(__OR1K_DELAY_COMPAT__)
+
+#define OR1K_DELAYED(a, b) a; b; l.nop
+#define OR1K_DELAYED_NOP(a) a; l.nop
+
+#else
+
+#error One of __OR1K_NODELAY__, __OR1K_DELAY__, or __OR1K_DELAY_COMPAT__ must be defined
+
+#endif
+
+#define LOAD_SYMBOL_2_GPR(gpr,symbol)  \
+	.global symbol ;               \
+	l.movhi gpr, hi(symbol) ;      \
+	l.ori   gpr, gpr, lo(symbol)
+#endif

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]