+2004-06-09 Toralf Lund <toralf@procaptura.com>
+
+ * arm/crt0.S: Copied from newlib and it now also sets up stacks for
+ FIQ and IRQ mode, plus calls hardware_init_hook() and
+ software_init_hook() if present.
+ * arm/libcfunc.c, arm/swi.h, arm/syscalls.c: Copied
+ from newlib.
+ * arm/Makefile.in: Build crt0.o, rdpmon-crt0.o, rdimon-crt0.o,
+ librdpmon.a, librdimon.a - support file for "bare" setup, as well
+ as "RDP" and "RDI" monitors.
+ * arm/coff-rdpmon.specs, arm/elf-rdpmon.specs,
+ arm/coff-rdimon.specs, arm/elf-rdimon.specs: gcc specs files to go
+ with above mentioned support libs and startfiles.
+
2004-06-03 Alexandre Oliva <aoliva@redhat.com>
* mn10300/sim.ld: Start at address 4, to avoid ambiguity with NULL
then echo ${objroot}/../binutils/objcopy ; \
else t='$(program_transform_name)'; echo objcopy | sed -e $$t ; fi`
-REDBOOT_OBJS = redboot-crt0.o redboot-syscalls.o
+CRT0 = crt0.o
+CRT0_INSTALL = install-crt0
+
+REDBOOT_CRT0 = redboot-crt0.o
+REDBOOT_OBJS = redboot-syscalls.o
REDBOOT_SCRIPTS = redboot.ld redboot.specs
REDBOOT_INSTALL = install-redboot
+
+RDPMON_CRT0 = rdpmon-crt0.o
+RDPMON_BSP = librdpmon.a
+RDPMON_OBJS = syscalls.o libcfunc.o trap.o
+RDPMON_SCRIPTS = rdpmon.specs
+RDPMON_INSTALL = install-rdpmon
+
+RDIMON_CRT0 = rdimon-crt0.o
+RDIMON_BSP = librdimon.a
+RDIMON_OBJS = rdimon-syscalls.o rdimon-libcfunc.o rdimon-trap.o
+RDIMON_SCRIPTS = rdimon.specs
+RDIMON_INSTALL = install-rdimon
+
CFLAGS = -g
# Here is all of the eval board stuff
# build a test program for each target board. Just trying to get
# it to link is a good test, so we ignore all the errors for now.
#
-all: ${REDBOOT_OBJS}
+all: ${CRT0} ${REDBOOT_CRT0} ${REDBOOT_OBJS} ${RDPMON_CRT0} ${RDPMON_BSP} ${RDIMON_CRT0} ${RDIMON_BSP}
#
# here's where we build the test programs for each target
test:
#
+crt0.o: crt0.S
redboot-crt0.o: redboot-crt0.S
redboot-syscalls.o: redboot-syscalls.c $(srcdir)/../syscall.h
+rdpmon-crt0.o: crt0.S
+ $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -DARM_RDP_MONITOR -o $@ -c $<
+
+rdimon-crt0.o: crt0.S
+ $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -DARM_RDI_MONITOR -o $@ -c $<
+
+rdimon-trap.o: trap.S
+ $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -DARM_RDI_MONITOR -o $@ -c $<
+
+rdimon-syscalls.o: syscalls.c
+ $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -DARM_RDI_MONITOR -o $@ -c $<
+
+rdimon-libcfunc.o: libcfunc.c
+ $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -DARM_RDI_MONITOR -o $@ -c $<
+
+$(RDPMON_BSP): $(RDPMON_OBJS)
+ ${AR} ${ARFLAGS} $@ $(IDTOBJS)
+ ${RANLIB} $@
+
+$(RDIMON_BSP): $(RDIMON_OBJS)
+ ${AR} ${ARFLAGS} $@ $(IDTOBJS)
+ ${RANLIB} $@
+
clean mostlyclean:
rm -f a.out core *.i *.o *-test *.srec *.dis *.x $(SIM_BSP) $(IQ80310_BSP)
rm -f Makefile config.status *~
.PHONY: install info install-info clean-info
-install: ${REDBOOT_INSTALL} ${IQ80310_INSTALL} ${PID_INSTALL}
+install: ${CRT0_INSTALL} ${REDBOOT_INSTALL} ${RDPMON_INSTALL} ${RDIMON_INSTALL} ${IQ80310_INSTALL} ${PID_INSTALL}
+install-crt0:
+ ${INSTALL_DATA} ${CRT0} ${tooldir}/lib${MULTISUBDIR}/$$x
install-redboot:
- set -e; for x in ${REDBOOT_OBJS}; do ${INSTALL_DATA} $$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+ set -e; for x in ${REDBOOT_CRT0} ${REDBOOT_OBJS}; do ${INSTALL_DATA} $$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
set -e; for x in ${REDBOOT_SCRIPTS}; do ${INSTALL_DATA} ${srcdir}/${objtype}$$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+install-rdpmon:
+ set -e; for x in ${RDPMON_CRT0} ${RDPMON_BSP}; do ${INSTALL_DATA} $$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+ set -e; for x in ${RDPMON_SCRIPTS}; do ${INSTALL_DATA} ${srcdir}/${objtype}$$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+
+install-rdimon:
+ set -e; for x in ${RDIMON_CRT0} ${RDIMON_BSP}; do ${INSTALL_DATA} $$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+ set -e; for x in ${RDIMON_SCRIPTS}; do ${INSTALL_DATA} ${srcdir}/${objtype}$$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
+
+
install-pid:
set -e; for x in ${PID_SCRIPTS}; do ${INSTALL_DATA} ${srcdir}/${objtype}$$x ${tooldir}/lib${MULTISUBDIR}/$$x; done
--- /dev/null
+%rename link old_link
+
+*link:
+%(old_link) -lrdimon
+
+*startfile:
+rdimon-crt0%O%s
+
--- /dev/null
+%rename link old_link
+
+*link:
+%(old_link) -lrdpmon
+
+*startfile:
+rdpmon-crt0%O%s
+
--- /dev/null
+#include "swi.h"
+
+/* ANSI concatenation macros. */
+#define CONCAT(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+#define FUNCTION( name ) CONCAT (__USER_LABEL_PREFIX__, name)
+#else
+#error __USER_LABEL_PREFIX is not defined
+#endif
+
+/* .text is used instead of .section .text so it works with arm-aout too. */
+ .text
+ .code 32
+ .align 0
+
+ .global _mainCRTStartup
+ .global _start
+ .global start
+start:
+_start:
+_mainCRTStartup:
+
+/* Start by setting up a stack */
+#ifdef ARM_RDP_MONITOR
+ /* Issue Demon SWI to read stack info */
+ swi SWI_GetEnv /* Returns command line in r0 */
+ mov sp,r1 /* and the highest memory address in r1 */
+ ldr sl, .LC2 /* stack limit is at end of data */
+ add sl, sl, #256 /* allow slop for stack overflow handling */
+ /* and small frames */
+#else
+#ifdef ARM_RDI_MONITOR
+ /* Issue Angel SWI to read stack info */
+ mov r0, #AngelSWI_Reason_HeapInfo
+ adr r1, .LC0 /* point at ptr to 4 words to receive data */
+ swi AngelSWI_ARM /* We are always in ARM mode for startup */
+ ldr r0, .LC0 /* point at values read */
+ ldr sp, [r0, #8]
+ ldr sl, [r0, #12]
+ add sl, sl, #256 /* allow slop for stack overflow handling */
+ /* and small frames */
+#else
+ /* Set up the stack pointer to a fixed value */
+ /* Changes by toralf:
+ - Allow linker script to provide stack via __stack symbol - see
+ defintion of .Lstack
+ - Provide "hooks" that may be used by the application to add
+ custom init code - see .Lhwinit and .Lswinit
+ - Go through all execution modes and set up stack for each of them.
+ Loosely based on init.s from ARM/Motorola example code.
+ Note: Mode switch via CPSR is not allowed once in non-privileged
+ mode, so we take care not to enter "User" to set up its sp,
+ and also skip most operations if already in that mode. */
+
+ ldr r3, .Lstack
+ cmp r3, #0
+ ldreq r3, .LC0
+ /* Note: This 'mov' is essential when starting in User, and ensures we
+ always get *some* sp value for the initial mode, even if we
+ have somehow missed it below (in which case it gets the same
+ value as FIQ - not ideal, but better than nothing.) */
+ mov sp, r3
+ mrs r2, CPSR
+ tst r2, #0x0F /* Test mode bits - in User of all are 0 */
+ beq .LC23 /* "eq" means r2 AND #0x0F is 0 */
+ msr CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled */
+ mov sp, r3
+ sub sl, sp, #0x1000 /* This mode also has its own sl (see below) */
+
+ mov r3, sl
+ msr CPSR_c, #0xD7 /* Abort mode, interrupts disabled */
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ msr CPSR_c, #0xDB /* Undefined mode, interrupts disabled */
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ msr CPSR_c, #0xD2 /* IRQ mode, interrupts disabled */
+ mov sp, r3
+ sub r3, r3, #0x2000
+
+ msr CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled */
+ mov sp, r3
+ sub r3, r3, #0x8000 /* Min size 32k */
+ bic r3, r3, #0x00FF /* Align with current 64k block */
+ bic r3, r3, #0xFF00
+
+ str r3, [r3, #-4] /* Move value into user mode sp without */
+ ldmdb r3, {sp}^ /* changing modes, via '^' form of ldm */
+
+ orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
+ msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1 */
+.LC23:
+ /* Setup a default stack-limit in-case the code has been
+ compiled with "-mapcs-stack-check". Hard-wiring this value
+ is not ideal, since there is currently no support for
+ checking that the heap and stack have not collided, or that
+ this default 64k is enough for the program being executed.
+ However, it ensures that this simple crt0 world will not
+ immediately cause an overflow event: */
+ sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl */
+#endif
+#endif
+ /* Zero the memory in the .bss section. */
+ mov a2, #0 /* Second arg: fill value */
+ mov fp, a2 /* Null frame pointer */
+ mov r7, a2 /* Null frame pointer for Thumb */
+
+ ldr a1, .LC1 /* First arg: start of memory block */
+ ldr a3, .LC2
+ sub a3, a3, a1 /* Third arg: length of block */
+
+
+#ifdef __thumb__ /* Enter Thumb mode.... */
+
+ add a4, pc, #1 /* Get the address of the Thumb block */
+ bx a4 /* Go there and start Thumb decoding */
+
+ .code 16
+ .global __change_mode
+ .thumb_func
+__change_mode:
+#endif
+
+ bl FUNCTION (memset)
+#if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
+/* Changes by toralf: Taken from libgloss/m68k/crt0.S
+ * initialize target specific stuff. Only execute these
+ * functions it they exist.
+ */
+ ldr r3, .Lhwinit
+ cmp r3, #0
+ beq .LC24
+ mov lr, pc
+ mov pc, r3
+.LC24:
+ ldr r3, .Lswinit
+ cmp r3, #0
+ beq .LC25
+ mov lr, pc
+ mov pc, r3
+.LC25:
+ mov r0, #0 /* no arguments */
+ mov r1, #0 /* no argv either */
+#else
+ /* Need to set up standard file handles */
+ bl FUNCTION (initialise_monitor_handles)
+
+#ifdef ARM_RDP_MONITOR
+ swi SWI_GetEnv /* sets r0 to point to the command line */
+ mov r1, r0
+#else
+ mov r0, #AngelSWI_Reason_GetCmdLine
+ adr r1, .LC30 /* Space for command line */
+ swi AngelSWI
+ ldr r1, .LC30
+#endif
+ /* Parse string at r1 */
+ mov r0, #0 /* count of arguments so far */
+ /* Push a NULL argument onto the end of the list. */
+#ifdef __thumb__
+ push {r0}
+#else
+ stmfd sp!, {r0}
+#endif
+.LC10:
+/* Skip leading blanks */
+#ifdef __thumb__
+ ldrb r3, [r1]
+ add r1, #1
+#else
+ ldrb r3, [r1], #1
+#endif
+ cmp r3, #0
+ beq .LC12
+ cmp r3, #' '
+ beq .LC10
+
+/* See whether we are scanning a string */
+ cmp r3, #'"'
+#ifdef __thumb__
+ beq .LC20
+ cmp r3, #'\''
+ bne .LC21
+.LC20:
+ mov r2, r3
+ b .LC22
+
+.LC21:
+ mov r2, #' ' /* terminator type */
+ sub r1, r1, #1 /* adjust back to point at start char */
+.LC22:
+#else
+ cmpne r3, #'\''
+ moveq r2, r3
+ movne r2, #' ' /* terminator type */
+ subne r1, r1, #1 /* adjust back to point at start char */
+#endif
+
+/* Stack a pointer to the current argument */
+#ifdef __thumb__
+ push {r1}
+#else
+ stmfd sp!, {r1}
+#endif
+ add r0, r0, #1
+.LC11:
+#ifdef __thumb__
+ ldrb r3, [r1]
+ add r1, #1
+#else
+ ldrb r3, [r1], #1
+#endif
+ cmp r3, #0
+ beq .LC12
+ cmp r2, r3 /* reached terminator? */
+ bne .LC11
+ mov r2, #0
+ sub r3, r1, #1
+ strb r2, [r3] /* terminate the arg string */
+ b .LC10
+
+.LC12:
+ mov r1, sp /* point at stacked arg pointers */
+ /* We've now got the stacked args in order reverse the */
+#ifdef __thumb__
+ mov r2, r0
+ lsl r2, #2
+ add r2, sp
+ mov r3, sp
+.LC15: cmp r2, r3
+ bls .LC14
+ sub r2, #4
+ ldr r4, [r2]
+ ldr r5, [r3]
+ str r5, [r2]
+ str r4, [r3]
+ add r3, #4
+ b .LC15
+.LC14:
+#else
+ add r2, sp, r0, LSL #2 /* End of args */
+ mov r3, sp /* Start of args */
+.LC13: cmp r2, r3
+ ldrhi r4,[r2, #-4] /* Reverse ends of list */
+ ldrhi r5, [r3]
+ strhi r5, [r2, #-4]!
+ strhi r4, [r3], #4
+ bhi .LC13
+#endif
+#endif
+
+#ifdef __USES_INITFINI__
+ /* Some arm/elf targets use the .init and .fini sections
+ to create constructors and destructors, and for these
+ targets we need to call the _init function and arrange
+ for _fini to be called at program exit. */
+ mov r4, r0
+ mov r5, r1
+ ldr r0, .Lfini
+ bl FUNCTION (atexit)
+ bl FUNCTION (_init)
+ mov r0, r4
+ mov r1, r5
+#endif
+ bl FUNCTION (main)
+
+ bl FUNCTION (exit) /* Should not return. */
+
+#ifdef __thumb__
+ /* Come out of Thumb mode. This code should be redundant. */
+
+ mov a4, pc
+ bx a4
+
+ .code 32
+ .global change_back
+change_back:
+ /* Halt the execution. This code should never be executed. */
+ /* With no debug monitor, this probably aborts (eventually).
+ With a Demon debug monitor, this halts cleanly.
+ With an Angel debug monitor, this will report 'Unknown SWI'. */
+ swi SWI_Exit
+#endif
+
+ /* For Thumb, constants must be after the code since only
+ positive offsets are supported for PC relative addresses. */
+
+ .align 0
+.LC0:
+#ifdef ARM_RDI_MONITOR
+ .word HeapBase
+#else
+#ifndef ARM_RDP_MONITOR
+ /* Changes by toralf: Provide alternative "stack" variable whose value
+ may be defined externally; .Lstack will be used instead of .LC0 if
+ it points to a non-0 value. Also set up references to "hooks" that
+ may be used by the application to provide additional init code. */
+
+#ifdef __pe__
+ .word 0x800000
+#else
+ .word 0x80000 /* Top of RAM on the PIE board. */
+#endif
+.Lstack:
+ .word __stack
+.Lhwinit:
+ .word FUNCTION (hardware_init_hook)
+.Lswinit:
+ .word FUNCTION (software_init_hook)
+
+ /* Set up defaults for the above variables in the form of weak symbols
+ - so that application will link correctly, and get value 0 in
+ runtime (meaning "ignore setting") for the variables, when the user
+ does not provide the symbols. (The linker uses a weak symbol if,
+ and only if, a normal version of the same symbol isn't provided
+ e.g. by a linker script or another object file.) */
+
+ .set __stack, 0
+ .set FUNCTION (hardware_init_hook), 0
+ .set FUNCTION (software_init_hook), 0
+
+ .weak __stack
+ .weak FUNCTION (hardware_init_hook)
+ .weak FUNCTION (software_init_hook)
+#endif
+
+#endif
+.LC1:
+ .word __bss_start__
+.LC2:
+ .word __bss_end__
+#ifdef __USES_INITFINI__
+.Lfini:
+ .word FUNCTION(_fini)
+#endif
+#ifdef ARM_RDI_MONITOR
+.LC30:
+ .word CommandLine
+ .word 255
+
+/* Workspace for Angel calls. */
+ .data
+/* Data returned by monitor SWI. */
+.global __stack_base__
+HeapBase: .word 0
+HeapLimit: .word 0
+__stack_base__: .word 0
+StackLimit: .word 0
+CommandLine: .space 256,0 /* Maximum length of 255 chars handled. */
+#endif
+
+#ifdef __pe__
+ .section .idata$3
+ .long 0,0,0,0,0,0,0,0
+#endif
--- /dev/null
+%rename link old_link
+
+*link:
+%(old_link) -lrdimon
+
+*startfile:
+crti%O%s crtbegin%O%s %{!pg:rdimon-crt0%O%s} %{pg:rdimon-crt0%O%s}
+
--- /dev/null
+%rename link old_link
+
+*link:
+%(old_link) -lrdpmon
+
+*startfile:
+crti%O%s crtbegin%O%s %{!pg:rdpmon-crt0%O%s} %{pg:rdpmon-crt0%O%s}
+
--- /dev/null
+/* Support files for GNU libc. Files in the C namespace go here.
+ Files in the system namespace (ie those that start with an underscore)
+ go in syscalls.c.
+
+ Note: These functions are in a seperate file so that OS providers can
+ overrride the system call stubs (defined in syscalls.c) without having
+ to provide libc funcitons as well. */
+#include "swi.h"
+
+#ifdef ARM_RDI_MONITOR
+
+static inline int
+do_AngelSWI (int reason, void * arg)
+{
+ int value;
+ asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0"
+ : "=r" (value) /* Outputs */
+ : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
+ : "r0", "r1", "lr"
+ /* Clobbers r0 and r1, and lr if in supervisor mode */);
+ return value;
+}
+#endif /* ARM_RDI_MONITOR */
+
+
+void
+abort (void)
+{
+#ifdef ARM_RDI_MONITOR
+ do_AngelSWI (AngelSWI_Reason_ReportException,
+ (void *) ADP_Stopped_RunTimeError);
+#else
+ asm ("mov r0,#17\nswi %a0" :: "i" (SWI_Exit));
+#endif
+}
+
+void
+alarm (void)
+{
+}
--- /dev/null
+/* SWI numbers for RDP (Demon) monitor. */
+#define SWI_WriteC 0x0
+#define SWI_Write0 0x2
+#define SWI_ReadC 0x4
+#define SWI_CLI 0x5
+#define SWI_GetEnv 0x10
+#define SWI_Exit 0x11
+#define SWI_EnterOS 0x16
+
+#define SWI_GetErrno 0x60
+#define SWI_Clock 0x61
+#define SWI_Time 0x63
+#define SWI_Remove 0x64
+#define SWI_Rename 0x65
+#define SWI_Open 0x66
+
+#define SWI_Close 0x68
+#define SWI_Write 0x69
+#define SWI_Read 0x6a
+#define SWI_Seek 0x6b
+#define SWI_Flen 0x6c
+
+#define SWI_IsTTY 0x6e
+#define SWI_TmpNam 0x6f
+#define SWI_InstallHandler 0x70
+#define SWI_GenerateError 0x71
+
+
+/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
+#define AngelSWI_ARM 0x123456
+#ifdef __thumb__
+#define AngelSWI 0xAB
+#else
+#define AngelSWI AngelSWI_ARM
+#endif
+
+/* The reason codes: */
+#define AngelSWI_Reason_Open 0x01
+#define AngelSWI_Reason_Close 0x02
+#define AngelSWI_Reason_WriteC 0x03
+#define AngelSWI_Reason_Write0 0x04
+#define AngelSWI_Reason_Write 0x05
+#define AngelSWI_Reason_Read 0x06
+#define AngelSWI_Reason_ReadC 0x07
+#define AngelSWI_Reason_IsTTY 0x09
+#define AngelSWI_Reason_Seek 0x0A
+#define AngelSWI_Reason_FLen 0x0C
+#define AngelSWI_Reason_TmpNam 0x0D
+#define AngelSWI_Reason_Remove 0x0E
+#define AngelSWI_Reason_Rename 0x0F
+#define AngelSWI_Reason_Clock 0x10
+#define AngelSWI_Reason_Time 0x11
+#define AngelSWI_Reason_System 0x12
+#define AngelSWI_Reason_Errno 0x13
+#define AngelSWI_Reason_GetCmdLine 0x15
+#define AngelSWI_Reason_HeapInfo 0x16
+#define AngelSWI_Reason_EnterSVC 0x17
+#define AngelSWI_Reason_ReportException 0x18
+#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
+#define ADP_Stopped_RunTimeError ((2 << 16) + 35)
--- /dev/null
+/* Support files for GNU libc. Files in the system namespace go here.
+ Files in the C namespace (ie those that do not start with an
+ underscore) go in .c. */
+
+#include <_ansi.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <errno.h>
+#include <reent.h>
+#include <unistd.h>
+#include "swi.h"
+
+/* Forward prototypes. */
+int _system _PARAMS ((const char *));
+int _rename _PARAMS ((const char *, const char *));
+int isatty _PARAMS ((int));
+clock_t _times _PARAMS ((struct tms *));
+int _gettimeofday _PARAMS ((struct timeval *, struct timezone *));
+void _raise _PARAMS ((void));
+int _unlink _PARAMS ((void));
+int _link _PARAMS ((void));
+int _stat _PARAMS ((const char *, struct stat *));
+int _fstat _PARAMS ((int, struct stat *));
+caddr_t _sbrk _PARAMS ((int));
+int _getpid _PARAMS ((int));
+int _kill _PARAMS ((int, int));
+void _exit _PARAMS ((int));
+int _close _PARAMS ((int));
+int _swiclose _PARAMS ((int));
+int _open _PARAMS ((const char *, int, ...));
+int _swiopen _PARAMS ((const char *, int));
+int _write _PARAMS ((int, char *, int));
+int _swiwrite _PARAMS ((int, char *, int));
+int _lseek _PARAMS ((int, int, int));
+int _swilseek _PARAMS ((int, int, int));
+int _read _PARAMS ((int, char *, int));
+int _swiread _PARAMS ((int, char *, int));
+void initialise_monitor_handles _PARAMS ((void));
+
+static int wrap _PARAMS ((int));
+static int error _PARAMS ((int));
+static int get_errno _PARAMS ((void));
+static int remap_handle _PARAMS ((int));
+static int do_AngelSWI _PARAMS ((int, void *));
+static int findslot _PARAMS ((int));
+
+/* Register name faking - works in collusion with the linker. */
+register char * stack_ptr asm ("sp");
+
+
+/* following is copied from libc/stdio/local.h to check std streams */
+extern void _EXFUN(__sinit,(struct _reent *));
+#define CHECK_INIT(fp) \
+ do \
+ { \
+ if ((fp)->_data == 0) \
+ (fp)->_data = _REENT; \
+ if (!(fp)->_data->__sdidinit) \
+ __sinit ((fp)->_data); \
+ } \
+ while (0)
+
+/* Adjust our internal handles to stay away from std* handles. */
+#define FILE_HANDLE_OFFSET (0x20)
+
+static int std_files_checked;
+static int monitor_stdin;
+static int monitor_stdout;
+static int monitor_stderr;
+
+/* Struct used to keep track of the file position, just so we
+ can implement fseek(fh,x,SEEK_CUR). */
+typedef struct
+{
+ int handle;
+ int pos;
+}
+poslog;
+
+#define MAX_OPEN_FILES 20
+static poslog openfiles [MAX_OPEN_FILES];
+
+static int
+findslot (int fh)
+{
+ int i;
+ for (i = 0; i < MAX_OPEN_FILES; i ++)
+ if (openfiles[i].handle == fh)
+ break;
+ return i;
+}
+
+#ifdef ARM_RDI_MONITOR
+
+static inline int
+do_AngelSWI (int reason, void * arg)
+{
+ int value;
+ asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0"
+ : "=r" (value) /* Outputs */
+ : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
+ : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
+ /* Clobbers r0 and r1, and lr if in supervisor mode */);
+ /* Accordingly to page 13-77 of ARM DUI 0040D other registers
+ can also be clobbered. Some memory positions may also be
+ changed by a system call, so they should not be kept in
+ registers. Note: we are assuming the manual is right and
+ Angel is respecting the APCS. */
+ return value;
+}
+#endif /* ARM_RDI_MONITOR */
+
+/* Function to convert std(in|out|err) handles to internal versions. */
+static int
+remap_handle (int fh)
+{
+ if (!std_files_checked)
+ {
+ CHECK_INIT(stdin);
+ CHECK_INIT(stdout);
+ CHECK_INIT(stderr);
+ std_files_checked = 1;
+ }
+ if (fh == STDIN_FILENO)
+ return monitor_stdin;
+ if (fh == STDOUT_FILENO)
+ return monitor_stdout;
+ if (fh == STDERR_FILENO)
+ return monitor_stderr;
+
+ return fh - FILE_HANDLE_OFFSET;
+}
+
+void
+initialise_monitor_handles (void)
+{
+ int i;
+
+#ifdef ARM_RDI_MONITOR
+ int volatile block[3];
+
+ block[0] = (int) ":tt";
+ block[2] = 3; /* length of filename */
+ block[1] = 0; /* mode "r" */
+ monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+
+ block[0] = (int) ":tt";
+ block[2] = 3; /* length of filename */
+ block[1] = 4; /* mode "w" */
+ monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+#else
+ int fh;
+ const char * name;
+
+ name = ":tt";
+ asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
+ : "=r"(fh)
+ : "i" (SWI_Open),"r"(name)
+ : "r0","r1");
+ monitor_stdin = fh;
+
+ name = ":tt";
+ asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
+ : "=r"(fh)
+ : "i" (SWI_Open),"r"(name)
+ : "r0","r1");
+ monitor_stdout = monitor_stderr = fh;
+#endif
+
+ for (i = 0; i < MAX_OPEN_FILES; i ++)
+ openfiles[i].handle = -1;
+
+ openfiles[0].handle = monitor_stdin;
+ openfiles[0].pos = 0;
+ openfiles[1].handle = monitor_stdout;
+ openfiles[1].pos = 0;
+}
+
+static int
+get_errno (void)
+{
+#ifdef ARM_RDI_MONITOR
+ return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
+#else
+ asm ("swi %a0" :: "i" (SWI_GetErrno));
+#endif
+}
+
+static int
+error (int result)
+{
+ errno = get_errno ();
+ return result;
+}
+
+static int
+wrap (int result)
+{
+ if (result == -1)
+ return error (-1);
+ return result;
+}
+
+/* Returns # chars not! written. */
+int
+_swiread (int file,
+ char * ptr,
+ int len)
+{
+ int fh = remap_handle (file);
+#ifdef ARM_RDI_MONITOR
+ int block[3];
+
+ block[0] = fh;
+ block[1] = (int) ptr;
+ block[2] = len;
+
+ return do_AngelSWI (AngelSWI_Reason_Read, block);
+#else
+ asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
+ : /* No outputs */
+ : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len)
+ : "r0","r1","r2");
+#endif
+}
+
+int
+_read (int file,
+ char * ptr,
+ int len)
+{
+ int slot = findslot (remap_handle (file));
+ int x = _swiread (file, ptr, len);
+
+ if (x < 0)
+ return error (-1);
+
+ if (slot != MAX_OPEN_FILES)
+ openfiles [slot].pos += len - x;
+
+ /* x == len is not an error, at least if we want feof() to work. */
+ return len - x;
+}
+
+int
+_swilseek (int file,
+ int ptr,
+ int dir)
+{
+ int res;
+ int fh = remap_handle (file);
+ int slot = findslot (fh);
+#ifdef ARM_RDI_MONITOR
+ int block[2];
+#endif
+
+ if (dir == SEEK_CUR)
+ {
+ if (slot == MAX_OPEN_FILES)
+ return -1;
+ ptr = openfiles[slot].pos + ptr;
+ dir = SEEK_SET;
+ }
+
+#ifdef ARM_RDI_MONITOR
+ if (dir == SEEK_END)
+ {
+ block[0] = fh;
+ ptr += do_AngelSWI (AngelSWI_Reason_FLen, block);
+ }
+
+ /* This code only does absolute seeks. */
+ block[0] = remap_handle (file);
+ block[1] = ptr;
+ res = do_AngelSWI (AngelSWI_Reason_Seek, block);
+#else
+ if (dir == SEEK_END)
+ {
+ asm ("mov r0, %2; swi %a1; mov %0, r0"
+ : "=r" (res)
+ : "i" (SWI_Flen), "r" (fh)
+ : "r0");
+ ptr += res;
+ }
+
+ /* This code only does absolute seeks. */
+ asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
+ : "=r" (res)
+ : "i" (SWI_Seek), "r" (fh), "r" (ptr)
+ : "r0", "r1");
+#endif
+
+ if (slot != MAX_OPEN_FILES && res == 0)
+ openfiles[slot].pos = ptr;
+
+ /* This is expected to return the position in the file. */
+ return res == 0 ? ptr : -1;
+}
+
+int
+_lseek (int file,
+ int ptr,
+ int dir)
+{
+ return wrap (_swilseek (file, ptr, dir));
+}
+
+/* Returns #chars not! written. */
+int
+_swiwrite (
+ int file,
+ char * ptr,
+ int len)
+{
+ int fh = remap_handle (file);
+#ifdef ARM_RDI_MONITOR
+ int block[3];
+
+ block[0] = fh;
+ block[1] = (int) ptr;
+ block[2] = len;
+
+ return do_AngelSWI (AngelSWI_Reason_Write, block);
+#else
+ asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
+ : /* No outputs */
+ : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len)
+ : "r0","r1","r2");
+#endif
+}
+
+int
+_write (int file,
+ char * ptr,
+ int len)
+{
+ int slot = findslot (remap_handle (file));
+ int x = _swiwrite (file, ptr,len);
+
+ if (x == -1 || x == len)
+ return error (-1);
+
+ if (slot != MAX_OPEN_FILES)
+ openfiles[slot].pos += len - x;
+
+ return len - x;
+}
+
+extern int strlen (const char *);
+
+int
+_swiopen (const char * path,
+ int flags)
+{
+ int aflags = 0, fh;
+#ifdef ARM_RDI_MONITOR
+ int block[3];
+#endif
+
+ int i = findslot (-1);
+
+ if (i == MAX_OPEN_FILES)
+ return -1;
+
+ /* The flags are Unix-style, so we need to convert them. */
+#ifdef O_BINARY
+ if (flags & O_BINARY)
+ aflags |= 1;
+#endif
+
+ if (flags & O_RDWR)
+ aflags |= 2;
+
+ if (flags & O_CREAT)
+ aflags |= 4;
+
+ if (flags & O_TRUNC)
+ aflags |= 4;
+
+ if (flags & O_APPEND)
+ {
+ aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */
+ aflags |= 8;
+ }
+
+#ifdef ARM_RDI_MONITOR
+ block[0] = (int) path;
+ block[2] = strlen (path);
+ block[1] = aflags;
+
+ fh = do_AngelSWI (AngelSWI_Reason_Open, block);
+
+#else
+ asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
+ : "=r"(fh)
+ : "i" (SWI_Open),"r"(path),"r"(aflags)
+ : "r0","r1");
+#endif
+
+ if (fh >= 0)
+ {
+ openfiles[i].handle = fh;
+ openfiles[i].pos = 0;
+ }
+
+ return fh >= 0 ? fh + FILE_HANDLE_OFFSET : error (fh);
+}
+
+int
+_open (const char * path,
+ int flags,
+ ...)
+{
+ return wrap (_swiopen (path, flags));
+}
+
+int
+_swiclose (int file)
+{
+ int myhan = remap_handle (file);
+ int slot = findslot (myhan);
+
+ if (slot != MAX_OPEN_FILES)
+ openfiles[slot].handle = -1;
+
+#ifdef ARM_RDI_MONITOR
+ return do_AngelSWI (AngelSWI_Reason_Close, & myhan);
+#else
+ asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");
+#endif
+}
+
+int
+_close (int file)
+{
+ return wrap (_swiclose (file));
+}
+
+void
+_exit (int n)
+{
+ /* FIXME: return code is thrown away. */
+
+#ifdef ARM_RDI_MONITOR
+ do_AngelSWI (AngelSWI_Reason_ReportException,
+ (void *) ADP_Stopped_ApplicationExit);
+#else
+ asm ("swi %a0" :: "i" (SWI_Exit));
+#endif
+ n = n;
+}
+
+int
+_kill (int n, int m)
+{
+#ifdef ARM_RDI_MONITOR
+ return do_AngelSWI (AngelSWI_Reason_ReportException,
+ (void *) ADP_Stopped_ApplicationExit);
+#else
+ asm ("swi %a0" :: "i" (SWI_Exit));
+#endif
+ n = n; m = m;
+}
+
+int
+_getpid (int n)
+{
+ return 1;
+ n = n;
+}
+
+caddr_t
+_sbrk (int incr)
+{
+ extern char end asm ("end"); /* Defined by the linker. */
+ static char * heap_end;
+ char * prev_heap_end;
+
+ if (heap_end == NULL)
+ heap_end = & end;
+
+ prev_heap_end = heap_end;
+
+ if (heap_end + incr > stack_ptr)
+ {
+ /* Some of the libstdc++-v3 tests rely upon detecting
+ out of memory errors, so do not abort here. */
+#if 0
+ extern void abort (void);
+
+ _write (1, "_sbrk: Heap and stack collision\n", 32);
+
+ abort ();
+#else
+ errno = ENOMEM;
+ return (caddr_t) -1;
+#endif
+ }
+
+ heap_end += incr;
+
+ return (caddr_t) prev_heap_end;
+}
+
+extern void memset (struct stat *, int, unsigned int);
+
+int
+_fstat (int file, struct stat * st)
+{
+ memset (st, 0, sizeof (* st));
+ st->st_mode = S_IFCHR;
+ st->st_blksize = 1024;
+ return 0;
+ file = file;
+}
+
+int _stat (const char *fname, struct stat *st)
+{
+ int file;
+
+ /* The best we can do is try to open the file readonly. If it exists,
+ then we can guess a few things about it. */
+ if ((file = _open (fname, O_RDONLY)) < 0)
+ return -1;
+
+ memset (st, 0, sizeof (* st));
+ st->st_mode = S_IFREG | S_IREAD;
+ st->st_blksize = 1024;
+ _swiclose (file); /* Not interested in the error. */
+ return 0;
+}
+
+int
+_link (void)
+{
+ return -1;
+}
+
+int
+_unlink (void)
+{
+ return -1;
+}
+
+void
+_raise (void)
+{
+ return;
+}
+
+int
+_gettimeofday (struct timeval * tp, struct timezone * tzp)
+{
+
+ if (tp)
+ {
+ /* Ask the host for the seconds since the Unix epoch. */
+#ifdef ARM_RDI_MONITOR
+ tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
+#else
+ {
+ int value;
+ asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0");
+ tp->tv_sec = value;
+ }
+#endif
+ tp->tv_usec = 0;
+ }
+
+ /* Return fixed data for the timezone. */
+ if (tzp)
+ {
+ tzp->tz_minuteswest = 0;
+ tzp->tz_dsttime = 0;
+ }
+
+ return 0;
+}
+
+/* Return a clock that ticks at 100Hz. */
+clock_t
+_times (struct tms * tp)
+{
+ clock_t timeval;
+
+#ifdef ARM_RDI_MONITOR
+ timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
+#else
+ asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
+#endif
+
+ if (tp)
+ {
+ tp->tms_utime = timeval; /* user time */
+ tp->tms_stime = 0; /* system time */
+ tp->tms_cutime = 0; /* user time, children */
+ tp->tms_cstime = 0; /* system time, children */
+ }
+
+ return timeval;
+};
+
+
+int
+isatty (int fd)
+{
+ return 1;
+ fd = fd;
+}
+
+int
+_system (const char *s)
+{
+ if (s == NULL)
+ return 0;
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+_rename (const char * oldpath, const char * newpath)
+{
+ errno = ENOSYS;
+ return -1;
+}
--- /dev/null
+ /* Run-time exception support */
+#include "swi.h"
+
+/* .text is used instead of .section .text so it works with arm-aout too. */
+ .text
+ .align 0
+ .global __rt_stkovf_split_big
+ .global __rt_stkovf_split_small
+
+/* The following functions are provided for software stack checking.
+ If hardware stack-checking is being used then the code can be
+ compiled without the PCS entry checks, and simply rely on VM
+ management to extend the stack for a thread.
+
+ The stack extension event occurs when the PCS function entry code
+ would result in a stack-pointer beneath the stack-limit register
+ value. The system relies on the following map:
+
+ +-----------------------------------+ <-- end of stack block
+ | ... |
+ | ... |
+ | active stack |
+ | ... | <-- sp (stack-pointer) somewhere in here
+ | ... |
+ +-----------------------------------+ <-- sl (stack-limit)
+ | stack-extension handler workspace |
+ +-----------------------------------+ <-- base of stack block
+
+ The "stack-extension handler workspace" is an amount of memory in
+ which the stack overflow support code must execute. It must be
+ large enough to deal with the worst case path through the extension
+ code. At the moment the compiler expects this to be AT LEAST
+ 256bytes. It uses this fact to code functions with small local
+ data usage within the overflow space.
+
+ In a true target environment We may need to increase the space
+ between sl and the true limit to allow for the stack extension
+ code, SWI handlers and for undefined instruction handlers of the
+ target environment. */
+
+__rt_stkovf_split_small:
+ mov ip,sp @ Ensure we can calculate the stack required
+ @ and fall through to...
+__rt_stkovf_split_big:
+ @ in: sp = current stack-pointer (beneath stack-limit)
+ @ sl = current stack-limit
+ @ ip = low stack point we require for the current function
+ @ lr = return address into the current function
+ @ fp = frame-pointer
+ @ original sp --> +----------------------------------+
+ @ | pc (12 ahead of PCS entry store) |
+ @ current fp ---> +----------------------------------+
+ @ | lr (on entry) pc (on exit) |
+ @ +----------------------------------+
+ @ | sp ("original sp" on entry) |
+ @ +----------------------------------+
+ @ | fp (on entry to function) |
+ @ +----------------------------------+
+ @ | |
+ @ | ..argument and work registers.. |
+ @ | |
+ @ current sp ---> +----------------------------------+
+ @
+ @ The "current sl" is somewhere between "original sp" and "current sp"
+ @ but above "true sl". The "current sl" should be at least 256bytes
+ @ above the "true sl". The 256byte stack guard should be large enough
+ @ to deal with the worst case function entry stacking (160bytes) plus
+ @ the stack overflow handler stacking requirements, plus the stack
+ @ required for the memory allocation routines.
+ @
+ @ Normal PCS entry (before stack overflow check) can stack 16
+ @ standard registers (64bytes) and 8 floating point registers
+ @ (96bytes). This gives a minimum stack guard of 160bytes (excluding
+ @ the stack required for the code). (Actually only a maximum of
+ @ 14standard registers are ever stacked on entry to a function).
+ @
+ @ NOTE: Structure returns are performed by the caller allocating a
+ @ dummy space on the stack and passing in a "phantom" arg1 into
+ @ the function. This means that we do not need to worry about
+ @ preserving the stack under "sp" even on function return.
+ @
+ @ Code should never poke values beneath sp. The sp register
+ @ should always be "dropped" first to cover the data. This
+ @ protects the data against any events that may try and use
+ @ the stack.
+
+ SUB ip, sp, ip @ extra stack required for function
+ @ Add stack extension code here. If desired a new stack chunk
+ @ can be allocated, and the register state updated suitably.
+
+ @ We now know how much extra stack the function requires.
+ @ Terminate the program for the moment:
+ swi SWI_Exit
arm*-*-elf | arm*-*-coff)
configdirs="${configdirs} arm testsuite";
;;
+ ep9312-*-elf | ep9312-*-coff)
+ configdirs="${configdirs} arm testsuite";
+ ;;
xscale-*-elf | xscale-*-coff)
configdirs="${configdirs} arm testsuite";
;;
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:822: checking for $ac_word" >&5
+echo "configure:825: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:852: checking for $ac_word" >&5
+echo "configure:855: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:901: checking whether we are using GNU C" >&5
+echo "configure:904: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:925: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:928: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:957: checking for $ac_word" >&5
+echo "configure:960: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:991: checking for $ac_word" >&5
+echo "configure:994: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
arm*-*-elf | arm*-*-coff)
configdirs="${configdirs} arm testsuite";
;;
+ ep9312-*-elf | ep9312-*-coff)
+ configdirs="${configdirs} arm testsuite";
+ ;;
xscale-*-elf | xscale-*-coff)
configdirs="${configdirs} arm testsuite";
;;