diff options
author | Ranjith Kumaran <ranjith@cygnus.com> | 2000-03-17 22:48:54 +0000 |
---|---|---|
committer | Ranjith Kumaran <ranjith@cygnus.com> | 2000-03-17 22:48:54 +0000 |
commit | 03261851a10dd2d6900a0a00a7515a0a46fb5d76 (patch) | |
tree | 7c22ac6cbbc99fd5cd1b5426853be8d4fd7bfcf1 /libgloss/sparc | |
parent | fae4c299f14fc23e2829c8656992eba21f79242a (diff) | |
download | newlib-03261851a10dd2d6900a0a00a7515a0a46fb5d76.zip newlib-03261851a10dd2d6900a0a00a7515a0a46fb5d76.tar.gz newlib-03261851a10dd2d6900a0a00a7515a0a46fb5d76.tar.bz2 |
20000317 sourceware import
Diffstat (limited to 'libgloss/sparc')
46 files changed, 10907 insertions, 0 deletions
diff --git a/libgloss/sparc/Makefile.in b/libgloss/sparc/Makefile.in new file mode 100644 index 0000000..fcf5448 --- /dev/null +++ b/libgloss/sparc/Makefile.in @@ -0,0 +1,286 @@ +# Copyright (c) 1995, 1996, 1997 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. + +# Makefile for libgloss/sparc. This is the board support +# code for the various sparc targets. + +VPATH = @srcdir@ +srcdir = @srcdir@ +objdir = . +srcroot = $(srcdir)/../.. +objroot = $(objdir)/../.. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ + +bindir = @bindir@ +libdir = @libdir@ +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@ +AR_FLAGS = qrv + +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` + +CYGMON_CRT0 = cygmon-crt0.o +CYGMON_BSP = libcygmon.a +CYGMON_OBJS = cygmon-salib.o + +701_CRT0 = crt0-701.o +701_BSP = libsplet701.a +701_OBJS = sysc-701.o salib-701.o sparclet-stub.o + +930_BSP = libslite930.a +931_BSP = libslite931.a +934_BSP = libslite934.a +86X_BSP = libslite86x.a + +# for the time being, built the stub without hardware breakpoint support +SLITE_OBJS = salib.o sparcl-stub.o cache.o + +# ERC32: SIS simulator, see sim/erc32. +ERC32_CRT0 = erc32-crt0.o +ERC32_BSP = liberc32.a +ERC32_OBJS = erc32-io.o traps.o erc32-stub.o debug.o fixctors.o +ERC32_ALL = $(ERC32_CRT0) $(ERC32_BSP) + +CRT0 = crt0.o +OBJS = close.o fstat.o getpid.o isatty.o kill.o \ + lseek.o open.o print.o putnum.o read.o sbrk.o stat.o \ + unlink.o write.o + +# This is set to one of SPARC, SLITE, or SPLET by configure. +# It's not clear what to do here. +# One could certainly build everything. The assembler supports all cpu +# variants (via runtime switches). However, the compiler [currently] doesn't. +# Of course, it may be the case that there isn't any cpu specific code in +# C source files, but there might be in the future. +CPU = @CPU@ + +# sparc stuff (not sparclite or sparclet) +SPARC_ALL = $(CYGMON_BSP) $(CYGMON_CRT0) $(objdir)/cygmon.ld +SPARC_INSTALL = sparc-install +SPARC_OBJ_FORMAT = sparc +SPARC_RAM_START = 0x4000 + +# sparc 64 stuff +SPARC64_ALL = $(CYGMON_BSP) $(CYGMON_CRT0) $(objdir)/cygmon.ld +SPARC64_INSTALL = sparc-install +SPARC64_OBJ_FORMAT = sparc:v9 +SPARC64_RAM_START = 0x4000 + +# sparclite stuff +SLITE_ALL = $(930_BSP) $(931_BSP) $(CYGMON_BSP) $(CYGMON_CRT0) $(objdir)/cygmon.ld $(934_BSP) $(86X_BSP) +SLITE_INSTALL = slite-install +SLITE_OBJ_FORMAT = sparc +SLITE_RAM_START = 0x40050000 + +# sparclet stuff +SPLET_ALL = $(701_CRT0) $(701_BSP) +SPLET_INSTALL = splet-install + +#### Host specific Makefile fragment comes in here. +@host_makefile_frag@ + +all: ${CRT0} $($(CPU)_ALL) $(ERC32_ALL) + +$(CYGMON_CRT0): cygmon-crt0.S + $(CC) $(CFLAGS_FOR_TARGET) $(CFLAGS) -DTARGET_CPU_$(CPU) $(INCLUDES) -o $@ -c $(srcdir)/cygmon-crt0.S + +$(CYGMON_BSP): $(CYGMON_OBJS) + @rm -f $@ + ${AR} ${AR_FLAGS} $@ $(CYGMON_OBJS) + ${RANLIB} $@ + +#$(STUBLIBS): $(OBJS) $(SLITE_OBJS) $(CRT0) +# ${CC} -nostdlib -r $(SLITE_OBJS) $(SHARED_OBJS) -o $(930_BSP) +# ${CC} -DSL931 -nostdlib -r $(SLITE_OBJS) $(SHARED_OBJS) -o $(931_BSP) +# ${CC} -nostdlib -r $(SLITE_OBJS) $(SHARED_OBJS) -o $(934_BSP) + +$(CRT0): $(srcdir)/crt0.S $(srcdir)/asm.h $(srcdir)/slite.h + $(CC) $(CFLAGS_FOR_TARGET) $(CFLAGS) $(INCLUDES) -o $@ -c $(srcdir)/crt0.S + +$(930_BSP) $(931_BSP) $(934_BSP) $(86X_BSP): $(OBJS) $(SLITE_OBJS) + @rm -f $@ + ${AR} ${AR_FLAGS} $@ $(OBJS) $(SLITE_OBJS) + ${RANLIB} $@ + +$(701_BSP): $(701_OBJS) + @rm -f $@ + ${AR} ${AR_FLAGS} $@ $(701_OBJS) + ${RANLIB} $@ + +erc32-crt0.o: $(srcdir)/erc32-crt0.S $(srcdir)/asm.h $(srcdir)/slite.h + $(CC) $(CFLAGS_FOR_TARGET) $(CFLAGS) $(INCLUDES) -o $@ -c $(srcdir)/erc32-crt0.S + +liberc32.a: $(OBJS) $(ERC32_OBJS) + @rm -f $@ + ${AR} ${AR_FLAGS} $@ $(OBJS) $(ERC32_OBJS) + ${RANLIB} $@ + +crt0-701.o: crt0-701.S +sysc-701.o: sysc-701.c +salib-701.o: salib-701.c +sparclet-stub.o: sparclet-stub.c +cygmon-salib.o: cygmon-salib.c + $(CC) -DTARGET_CPU_$(CPU) $(CFLAGS_FOR_TARGET) $(CFLAGS) $(INCLUDES) -o $@ -c $(srcdir)/cygmon-salib.c +cache.o: $(srcdir)/cache.c +salib.o: $(srcdir)/salib.c +win.o: $(srcdir)/win.S +syscalls.o: $(srcdir)/syscalls.c +sparcl-stub.o: $(srcdir)/sparcl-stub.c $(srcdir)/../debug.h $(srcdir)/../debug.c +erc32-stub.o: $(srcdir)/erc32-stub.c $(srcdir)/../debug.h $(srcdir)/../debug.c +fixctors.o : $(srcdir)/fixctors.c + +$(objdir)/cygmon.ld: @CYGMONLDSCRIPTTEMPL@ + sed 's/TARGET_OBJ_FORMAT/$($(CPU)_OBJ_FORMAT)/g;s/TARGET_RAM_START/$($(CPU)_RAM_START)/g;' < $(<) > $(objdir)/cygmon.ld + +install: $($(CPU)_INSTALL) + $(INSTALL_DATA) $(CRT0) $(tooldir)/lib${MULTISUBDIR}/$(CRT0) + +sparc-install: + $(INSTALL_DATA) $(CYGMON_BSP) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(CYGMON_OBJS) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(objdir)/cygmon.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(CYGMON_CRT0) $(tooldir)/lib${MULTISUBDIR} + +slite-install: + $(INSTALL_DATA) $(930_BSP) $(tooldir)/lib${MULTISUBDIR}/$(930_BSP) + $(INSTALL_DATA) $(931_BSP) $(tooldir)/lib${MULTISUBDIR}/$(931_BSP) + $(INSTALL_DATA) $(934_BSP) $(tooldir)/lib${MULTISUBDIR}/$(934_BSP) + $(INSTALL_DATA) $(86X_BSP) $(tooldir)/lib${MULTISUBDIR}/$(86X_BSP) + $(INSTALL_DATA) $(srcdir)/ex930.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(srcdir)/ex931.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(srcdir)/ex934.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(srcdir)/sparc86x.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(srcdir)/elfsim.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(ERC32_CRT0) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(ERC32_BSP) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(objdir)/traps.o $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(CYGMON_BSP) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(CYGMON_OBJS) $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(objdir)/cygmon.ld $(tooldir)/lib${MULTISUBDIR} + $(INSTALL_DATA) $(CYGMON_CRT0) $(tooldir)/lib${MULTISUBDIR} + +splet-install: + $(INSTALL_DATA) $(701_CRT0) $(tooldir)/lib${MULTISUBDIR}/$(701_CRT0) + $(INSTALL_DATA) $(701_BSP) $(tooldir)/lib${MULTISUBDIR}/$(701_BSP) + $(INSTALL_DATA) $(srcdir)/tsc701.ld $(tooldir)/lib${MULTISUBDIR} + +# Make a simple test case to test the linker script, startup code, and +# I/O code +# +test: ex930-test.x ex931-test.x erc32-test.x + @echo Done... + +# compile a fully linked binary. The -N option is for a.out, so the +# base address will be zero, rather than the default of 0x2020. The +# -Wl,-T*.ld is for the linker script. By using -Wl, the linker script +# is put on the proper place in the comand line for ld, and all the +# symbols will get fully resolved. + +erc32-test.x: test.o ${ERC32_CRT0} ${srcdir}/erc32.ld Makefile ${ERC32_BSP} + ${CC} -L${srcdir} -L${objdir} test.o -o $@ $(LDFLAGS_FOR_TARGET) \ + -N -Wl,-Terc32.ld -Wl,-Map -Wl,erc32.map -nostdlib +erc32-test.srec: erc32-test.x + $(OBJCOPY) -O srec erc32-test.x $@ +erc32-test.dis: erc32-test.x + @rm -fr erc32-test.dis + $(OBJDUMP) -d erc32-test.x > $@ +erc32-test: erc32-test.srec erc32-test.dis + +ex930-test.x: test.o ${CRT0} ${srcdir}/ex930.ld Makefile ${930_BSP} + ${CC} -L${srcdir} -L${objdir} test.o -o $@ $(LDFLAGS_FOR_TARGET) \ + -N -Wl,-Tex930.ld -nostdlib +ex930-test.srec: ex930-test.x + $(OBJCOPY) -O srec ex930-test.x $@ +ex930-test.dis: ex930-test.x + @rm -fr ex930-test.dis + $(OBJDUMP) -d ex930-test.x > $@ +ex930-test: ex930-test.srec ex930-test.dis + +ex931-test.x: test.o ${CRT0} ${srcdir}/ex931.ld Makefile ${931_BSP} + ${CC} -L${srcdir} -L${objdir} test.o -o $@ $(LDFLAGS_FOR_TARGET) \ + -N -Wl,-Tex931.ld -nostdlib +ex931-test.srec: ex931-test.x + $(OBJCOPY) -O srec ex931-test.x $@ +ex931-test.dis: ex931-test.x + @rm -fr ex931-test.dis + $(OBJDUMP) -d ex931-test.x > $@ +ex931-test: ex931-test.srec ex931-test.dis + +ex934-test.x: test.o ${CRT0} ${srcdir}/ex934.ld Makefile ${934_BSP} + ${CC} -L${srcdir} -L${objdir} test.o -o $@ $(LDFLAGS_FOR_TARGET) \ + -N -Wl,-Tex934.ld -nostdlib +ex934-test.srec: ex934-test.x + $(OBJCOPY) -O srec ex934-test.x $@ +ex934-test.dis: ex934-test.x + @rm -fr ex934-test.dis + $(OBJDUMP) -d ex934-test.x > $@ +ex934-test: ex934-test.srec ex934-test.dis + +# a C++ test case +dtor.o: $(srcdir)/dtor.C + $(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -o $@ -c $? +dtor.dis: dtor.x + @rm -fr dtor.dis + $(OBJDUMP) -d dtor.x > $@ +dtor.x: dtor.o ${ERC32_CRT0} ${srcdir}/erc32.ld Makefile ${ERC32_BSP} + ${CC} -L${srcdir} -L${objdir} dtor.o -o $@ $(LIBS_FOR_TARGET) \ + -N -Wl,-Terc32.ld + +# target specific makefile fragment comes in here. +@target_makefile_frag@ + +clean mostlyclean: + rm -f *.o *.a *.map *.x + +distclean maintainer-clean realclean: clean + rm -f Makefile config.cache config.log config.status + +.PHONY: info dvi doc install-info clean-info +info doc dvi: +install-info: +clean-info: + +Makefile: Makefile.in config.status @host_makefile_frag_path@ \ + @target_makefile_frag_path@ + $(SHELL) config.status + +config.status: configure + $(SHELL) config.status --recheck diff --git a/libgloss/sparc/asm.h b/libgloss/sparc/asm.h new file mode 100644 index 0000000..daeff34 --- /dev/null +++ b/libgloss/sparc/asm.h @@ -0,0 +1,39 @@ +/* asm.h -- macros for sparc asm + * + * Copyright (c) 1996 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. + */ + +#ifndef __SPARC_ASM_h +#define __SPARC_ASM_h + +/* Indicate we are in an assembly file and get the basic CPU definitions. */ +#define ASM + +/* ANSI concatenation macros. */ +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. + Note that it's too late to have coff have no underscores + (would break user programs). + One school of thought likes having underscores for both a.out and coff + (simplicity in consistency). */ +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__,x) + +/* STRINGSYM makes a string out of a symbol name with the proper assembly + prefix. Useful for inline assembly language in C source files. */ +#define STRINGIT2(x) #x +#define STRINGIT1(x) STRINGIT2(x) +#define STRINGSYM(x) STRINGIT1(SYM(x)) + +#endif diff --git a/libgloss/sparc/cache.c b/libgloss/sparc/cache.c new file mode 100644 index 0000000..5b6e270 --- /dev/null +++ b/libgloss/sparc/cache.c @@ -0,0 +1,147 @@ +/* Cache code for SPARClite + * + * 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. + */ + +#include "sparclite.h" + +/* Ancillary registers on the DANlite */ + +#define DIAG 30 +#define ICCR 31 + +/* Bits in the DIAG register */ + +#define ICD 0x40000000 /* ICACHE disable */ +#define DCD 0x20000000 /* DCACHE disable */ + +/* Bits in the ICCR register */ + +#define CE 1 /* cache enable*/ + + +/* Forward declarations. */ + +void flush_i_cache (); + + +/* Determine if this is a DANlite (MB8686x), as opposed to an earlier + SPARClite (MB8683x). This is done by examining the impl and ver + fields in the PSR: + + MB8683x: impl(bit31-28)=0x0; ver(bit27-24)=0xf; + MB8686x: impl(bit31-28)=0x1; ver(bit27-24)=0xe; +*/ + +static int +is_danlite () +{ + static int checked = 0; + static int danlite = 0; + + if (!checked) + { + int psr = read_psr (); + danlite = (psr & 0xff000000) == 0x1e000000; + checked = 1; + } + return danlite; +} + +/* This cache code is known to work on both the 930 & 932 processors. It just + cheats and clears the all of the address space that could contain tags, as + opposed to striding the tags at 8 or 16 word intervals, or using the cache + flush registers, which don't exist on all processors. */ + +void +cache_off () +{ + if (is_danlite ()) + { + /* Disable the ICACHE. Disabling the DCACHE crashes the machine. */ + unsigned int diag = read_asr (DIAG); + write_asr (DIAG, diag | ICD); + } + else + { + write_asi (1, 0, 0); + } +} + +void +cache_on () +{ + if (is_danlite ()) + { + unsigned int diag; + + /* Flush the caches. */ + flush_i_cache (); + + /* Enable the ICACHE and DCACHE */ + diag = read_asr (DIAG); + write_asr (DIAG, diag & ~ (ICD | DCD)); + } + else + { + unsigned long addr; + + cache_off (); /* Make sure the cache is off */ + + /* Reset all of the cache line valid bits */ + + for (addr = 0; addr < 0x1000; addr += 8) + { + write_asi (0xc, addr, 0); /* Clear bank 1, icache */ + write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */ + + write_asi (0xe, addr, 0); /* Clear bank 1, dcache */ + write_asi (0xe, addr + 0x80000000, 0); /* Clear bank 2, dcache */ + } + + /* turn on the cache */ + + write_asi (1, 0, 0x35); /* Write buf ena, prefetch buf ena, data + & inst caches enab */ + } +} + +/* Flush the instruction cache. We need to do this for the debugger stub so + that breakpoints, et. al. become visible to the instruction stream after + storing them in memory. + */ + +void +flush_i_cache () +{ + if (is_danlite ()) + { + write_asi (0x31, 0, 0); /* Flush entire i/d caches */ + } + else + { + int cache_reg; + unsigned long addr; + + cache_reg = read_asi (1, 0); /* Read cache/bus interface reg */ + + if (!(cache_reg & 1)) + return; /* Just return if cache is already off */ + + for (addr = 0; addr < 0x1000; addr += 8) + { + write_asi (0xc, addr, 0); /* Clear bank 1, icache */ + write_asi (0xc, addr + 0x80000000, 0); /* Clear bank 2, icache */ + } + } +} diff --git a/libgloss/sparc/configure b/libgloss/sparc/configure new file mode 100755 index 0000000..8c5c76c --- /dev/null +++ b/libgloss/sparc/configure @@ -0,0 +1,1201 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.1 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.1" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=sparc-stub.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +if test "${enable_shared}" = "yes" ; then + echo "Shared libraries not supported for cross compiling, ignored" +fi + +if test "$srcdir" = "." ; then + if test "${with_target_subdir}" != "." ; then + libgloss_topdir="${with_multisrctop}../../.." + else + libgloss_topdir="${with_multisrctop}../.." + fi +else + libgloss_topdir="${srcdir}/../.." +fi + +ac_aux_dir= +for ac_dir in $libgloss_topdir $srcdir/$libgloss_topdir; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $libgloss_topdir $srcdir/$libgloss_topdir" 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:570: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:649: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:670: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:688: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +# FIXME: We temporarily define our own version of AC_PROG_CC. This is +# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We +# are probably using a cross compiler, which will not be able to fully +# link an executable. This should really be fixed in autoconf +# itself. + + + +# 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:722: 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 + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # 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:751: 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 + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:799: 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 + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:808: \"$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 +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:823: 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 + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +AS=${AS-as} + +AR=${AR-ar} + +LD=${LD-ld} + +# 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:859: 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 + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +case ${target_cpu} in +sparclite*) CPU=SLITE ;; +sparclet*) CPU=SPLET ;; +sparc64*) CPU=SPARC64 ;; +sparc86x*) CPU=SLITE ;; +*) CPU=SPARC ;; +esac + + +case ${target_cpu} in +sparc64*) CYGMONLDSCRIPTTEMPL=${srcdir}/cygmon-sparc64-ld.src ;; +*) CYGMONLDSCRIPTTEMPL=${srcdir}/cygmon.ld.src +esac + +host_makefile_frag=${srcdir}/../config/default.mh +target_makefile_frag=${srcdir}/../config/default.mt + +host_makefile_frag_path=$host_makefile_frag + + +target_makefile_frag_path=$target_makefile_frag + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.1" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@AS@%$AS%g +s%@AR@%$AR%g +s%@LD@%$LD%g +s%@RANLIB@%$RANLIB%g +s%@CPU@%$CPU%g +s%@host_makefile_frag_path@%$host_makefile_frag_path%g +/@host_makefile_frag@/r $host_makefile_frag +s%@host_makefile_frag@%%g +s%@target_makefile_frag_path@%$target_makefile_frag_path%g +/@target_makefile_frag@/r $target_makefile_frag +s%@target_makefile_frag@%%g +s%@CYGMONLDSCRIPTTEMPL@%$CYGMONLDSCRIPTTEMPL%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <<EOF +srcdir=${srcdir} +target=${target} +ac_configure_args="${ac_configure_args} --enable-multilib" +CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +libgloss_topdir=${libgloss_topdir} + +EOF +cat >> $CONFIG_STATUS <<\EOF +. ${libgloss_topdir}/config-ml.in +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/libgloss/sparc/configure.in b/libgloss/sparc/configure.in new file mode 100644 index 0000000..c836f6c --- /dev/null +++ b/libgloss/sparc/configure.in @@ -0,0 +1,120 @@ +# Copyright (c) 1995, 1996 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. +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.5)dnl +AC_INIT(sparc-stub.c) + +if test "${enable_shared}" = "yes" ; then + echo "Shared libraries not supported for cross compiling, ignored" +fi + +if test "$srcdir" = "." ; then + if test "${with_target_subdir}" != "." ; then + libgloss_topdir="${with_multisrctop}../../.." + else + libgloss_topdir="${with_multisrctop}../.." + fi +else + libgloss_topdir="${srcdir}/../.." +fi + +AC_CONFIG_AUX_DIR($libgloss_topdir) + +AC_PROG_INSTALL + +AC_CANONICAL_SYSTEM + +# FIXME: We temporarily define our own version of AC_PROG_CC. This is +# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We +# are probably using a cross compiler, which will not be able to fully +# link an executable. This should really be fixed in autoconf +# itself. + +AC_DEFUN(LIB_AC_PROG_CC, +[AC_BEFORE([$0], [AC_PROG_CPP])dnl +AC_CHECK_PROG(CC, gcc, gcc) +if test -z "$CC"; then + AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc) + test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) +fi + +AC_PROG_CC_GNU + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +dnl Check whether -g works, even if CFLAGS is set, in case the package +dnl plays around with CFLAGS (such as to build both debugging and +dnl normal versions of a library), tasteless as that idea is. + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + AC_PROG_CC_G + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi +]) + +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 + +case ${target_cpu} in +sparclite*) CPU=SLITE ;; +sparclet*) CPU=SPLET ;; +sparc64*) CPU=SPARC64 ;; +sparc86x*) CPU=SLITE ;; +*) CPU=SPARC ;; +esac +AC_SUBST(CPU) + +case ${target_cpu} in +sparc64*) CYGMONLDSCRIPTTEMPL=${srcdir}/cygmon-sparc64-ld.src ;; +*) CYGMONLDSCRIPTTEMPL=${srcdir}/cygmon.ld.src +esac + +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_SUBST(CYGMONLDSCRIPTTEMPL) + +AC_OUTPUT(Makefile, +. ${libgloss_topdir}/config-ml.in, +srcdir=${srcdir} +target=${target} +ac_configure_args="${ac_configure_args} --enable-multilib" +CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +libgloss_topdir=${libgloss_topdir} +) + diff --git a/libgloss/sparc/crt0-701.S b/libgloss/sparc/crt0-701.S new file mode 100644 index 0000000..44ffadc --- /dev/null +++ b/libgloss/sparc/crt0-701.S @@ -0,0 +1,105 @@ +/* crt0.S for the sparclet 701. + + At the moment, all the necessary syscalls are here. + Convention has them in a separate file but libgloss is still in + too much flux. */ + + .text + + .global start +start: + +! zero bss + + sethi %hi(_end), %o1 + or %o1, %lo(_end), %o1 + sethi %hi(_edata), %o0 + or %o0, %lo (_edata), %o0 + sub %o1, %o0, %o1 +Lzero_bss: + subcc %o1, 4, %o1 + clr [%o0] + bne Lzero_bss + add %o0, 4, %o0 + +! set up argc, argv, envp (?) + + ld [%sp+64], %o0 + sll %o0, 2, %o2 + add %o2, 4, %o2 + add %sp, 68, %o1 + add %o1, %o2, %o2 + sethi %hi(_environ), %o3 + st %o2, [%o3+%lo(_environ)] + +! call main, exit + + call _main + sub %sp, 32, %sp + call _exit + nop + +! void _exit (int rc) + + .global __exit +__exit: + mov 1, %g1 + ta 0 +! If that does not work, just loop forever. +Lloop_forever: + b Lloop_forever + nop + +! int _open (char *, int) + + .global _open +_open: + mov 5, %g1 + ta 0 + bcc Lnoerr + nop + b Lcerror + nop + +! int _close (int) + + .global _close +_close: + mov 6, %g1 + ta 0 + bcc Lnoerr + nop + b Lcerror + nop + +! int read (int, char *, int) + + .global _read +_read: + mov 3, %g1 + ta 0 + bcc Lnoerr + nop + b Lcerror + nop + +! int write (int, char *, int) + + .global _write +_write: + mov 4, %g1 + ta 0 + bcc Lnoerr + nop + b Lcerror + nop + +Lnoerr: + retl + nop + +Lcerror: + sethi %hi(__impure_ptr), %g1 + st %o0, [%g1+%lo(__impure_ptr)] + retl + mov -1, %o0 diff --git a/libgloss/sparc/crt0.S b/libgloss/sparc/crt0.S new file mode 100644 index 0000000..90e18c5 --- /dev/null +++ b/libgloss/sparc/crt0.S @@ -0,0 +1,186 @@ +/* + * C startup code for the Fujitsu SPARClite demo board + * + * Copyright (c) 1995, 1996 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. + */ +#include "asm.h" + +.data + .align 8 + .ascii "DaTa" ! this is the first address in the data section + .long SYM(sdata) +SYM(environ): + .long 0 + + .text + .align 8 + + .globl SYM(_start) +SYM(_start): + .globl SYM(start) +SYM(start): + /* see if the stack is already setup. if not, then default + * to using the value of %sp as set by the ROM monitor + */ + sethi %hi(__stack), %g1 + or %g1,%lo(__stack),%g1 + cmp %g0,%g1 + be 1f + mov %g1, %sp ! set the stack pointer + mov %sp, %fp +1: + + /* zero the bss section */ + sethi %hi(__bss_start),%g2 + or %g2,%lo(__bss_start),%g2 ! start of bss + sethi %hi(_end),%g3 + or %g3,%lo(_end),%g3 ! end of bss + mov %g0,%g1 ! so std has two zeros +zerobss: + std %g0,[%g2] + add %g2,8,%g2 + cmp %g2,%g3 + bleu,a zerobss + nop + +/* + * copy prom & trap vectors to sram. + */ + set 0x30000000, %l0 + set 0xfff8, %l1 + tst %l1 ! Set condition codes + +copyloop: + ldd [%l1], %l2 + std %l2, [%l0 + %l1] + bg copyloop + deccc 8, %l1 + + set 0x30000000, %l0 ! Base of new trap vector + mov %l0, %tbr ! Install the new tbr + + set SYM(win_ovf_trap), %l1 ! Setup window overflow trap + ldd [%l1], %l2 + std %l2, [%l0 + 5 * 16] + ldd [%l1 + 8], %l2 + std %l2, [%l0 + 5 * 16 + 8] + + set SYM(win_unf_trap), %l1 ! Setup window underflow trap + ldd [%l1], %l2 + std %l2, [%l0 + 6 * 16] + ldd [%l1 + 8], %l2 + std %l2, [%l0 + 6 * 16 + 8] + +/* + * Try enabling the FPU by setting EF. If that causes a trap, then we probably + * don't have an FPU. + */ + + ldd [%l0 + 2 * 16], %l4 ! Save original trap routine + set SYM(no_fpu_trap), %l1 ! Install new one + ldd [%l1], %l2 + std %l2, [%l0 + 2 * 16] + + mov %psr, %l0 + sethi %hi(0x1000), %l1 + bset %l1, %l0 +! mov %l0, %psr + + std %l4, [2 * 16] ! Restore original trap routine + + +/* + * Move the data segment from it's ROM address to RAM where it + * belongs. + */ + +relocd: +#if 0 /* This code is broken. FIXME */ + set (_sdata),%g2 ! %g2 = start of data in aout file + set SYM(environ),%g4 ! %g4 = actual data base address + set (_edata),%g3 ! %g3 = end of where data should go + subcc %g3, %g4, %g5 ! %g5 = length of data + + subcc %g4, %g2, %g0 ! need to relocate data ? + ble init + ld [%g4], %g6 + subcc %g6, 1, %g0 + be init +mvdata: + subcc %g5, 8, %g5 + ldd [%g2 + %g5], %g6 + bg mvdata +#endif + +/* + * initialize target specific stuff. Only execute these + * functions it they exist. + */ +init: + sethi %hi(SYM(hardware_init_hook)), %g1 + or %g1,%lo(SYM(hardware_init_hook)),%g1 + cmp %g0,%g1 + be 1f + nop + call SYM(hardware_init_hook) + nop + +1: + sethi %hi(SYM(software_init_hook)), %g1 + or %g1,%lo(SYM(software_init_hook)),%g1 + cmp %g0,%g1 + be 2f + nop + call SYM(software_init_hook) + nop +2: + call SYM(main) + nop + + /* call exit from the C library so atexit gets called, and the + * C++ destructors get run. This calls our exit routine below + * when it's done. + */ + call SYM(exit) + nop + +/* + * This should drop control back to the ROM monitor, if there is + * one. + */ + .globl SYM(_exit) +SYM(_exit): + call 0 + nop + +/* + * Trap handlers. + */ + + .align 8 + +SYM(win_ovf_trap): + sethi %hi(SYM(win_ovf)), %l3 + jmpl %lo(SYM(win_ovf))+%l3, %g0 + mov %wim, %l0 + nop + +SYM(win_unf_trap): + sethi %hi(SYM(win_unf)), %l3 + jmpl %lo(SYM(win_unf))+%l3, %g0 + mov %wim, %l0 + nop + +SYM(no_fpu_trap): ! Come here when no fpu exists. + jmpl %l2, %g0 ! This just skips the + rett %l2+4 ! offending instruction. diff --git a/libgloss/sparc/cygmon-crt0.S b/libgloss/sparc/cygmon-crt0.S new file mode 100644 index 0000000..272c00d --- /dev/null +++ b/libgloss/sparc/cygmon-crt0.S @@ -0,0 +1,144 @@ +/* + * C startup code for the Fujitsu SPARClite demo board + * + * Copyright (c) 1995, 1996 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. + */ +#include "asm.h" + +#ifdef TARGET_CPU_SPARC64 +#define STACK_BIAS 2047 +#define SAVE_SIZE -128 +#else +#define SAVE_SIZE -64 +#endif + +.data + .align 8 +SYM(environ): ! this is the first address in the data section + .long 0 + +SYM(argc): + .long 0 + + .text + .align 8 + + .globl SYM(start) + .globl start +SYM(start): +start: + /* see if the stack is already setup. if not, then default + * to using the value of %sp as set by the ROM monitor + */ + sethi %hi(__stack), %g1 + or %g1,%lo(__stack),%g1 + cmp %g0,%g1 + be 1f + nop +#ifdef STACK_BIAS + sub %g1, STACK_BIAS, %g1 +#endif + mov %g1, %sp ! set the stack pointer + mov 0, %fp +1: + + /* zero the bss section */ + sethi %hi(__bss_start),%g2 + or %g2,%lo(__bss_start),%g2 ! start of bss + sethi %hi(_end),%g3 + or %g3,%lo(_end),%g3 ! end of bss + mov %g0,%g1 ! so std has two zeros +zerobss: + std %g0,[%g2] + add %g2,8,%g2 + cmp %g2,%g3 + bleu,a zerobss + nop + +/* + * initialize target specific stuff. Only execute these + * functions it they exist. + */ +init: + sethi %hi(SYM(hardware_init_hook)), %g1 + or %g1,%lo(SYM(hardware_init_hook)),%g1 + cmp %g0,%g1 + be 1f + nop + call SYM(hardware_init_hook) + nop + +1: + sethi %hi(SYM(software_init_hook)), %g1 + or %g1,%lo(SYM(software_init_hook)),%g1 + cmp %g0,%g1 + be 2f + nop + call SYM(software_init_hook) + nop +2: + set SYM(__sigtramp), %o0 + call SYM(__install_signal_handler) + nop + + set do_dtors,%o0 + call SYM(atexit) + nop + + call do_ctors + nop + + set SYM(argc), %o0 + call SYM(__getProgramArgs) + nop + + mov %o0, %o1 + set SYM(argc), %o0 + ld [%o0], %o0 + call SYM(main) + nop + + /* call exit from the C library so atexit gets called, and the + * C++ destructors get run. This calls our exit routine below + * when it's done. + */ + call SYM(exit) + nop + +do_ctors: + save %sp,SAVE_SIZE,%sp + set __CTOR_LIST__,%l0 +our_entry: + ld [%l0],%l1 + add %l0,4,%l0 + tst %l1 +1: + beq 2f + nop + ld [%l0],%l2 + add %l0,4,%l0 + + call %l2 + nop + deccc %l1 + b 1b + nop +2: + ret + restore + +do_dtors: + save %sp,SAVE_SIZE,%sp + set __DTOR_LIST__,%l0 + b our_entry + nop diff --git a/libgloss/sparc/cygmon-salib.c b/libgloss/sparc/cygmon-salib.c new file mode 100644 index 0000000..4f65c0f --- /dev/null +++ b/libgloss/sparc/cygmon-salib.c @@ -0,0 +1,220 @@ +#ifdef TARGET_CPU_SPARC64 +#include <sys/types.h> +#endif +#include <sys/time.h> + +void +putTtyChar(int c) +{ + /* 2 is fork under solaris; bad juju */ + asm(" mov %i0,%o0 + or %g0,2,%g1 + ta 8 + nop"); +} + +int +write(int fd,char *ptr,int amt) +{ + if (fd < 0 || fd > 2) + { + return -1; + } + asm(" or %g0, 4, %g1 + ta 8 + nop"); + return amt; +} + +int +read(int fd,char *ptr,int amt) +{ + if (fd < 0 || fd > 2) + { + return -1; + } + asm(" or %g0, 3, %g1 + ta 8 + nop"); + return amt; +} + +void +_exit(int code) +{ + while(1) { + asm(" or %g0,1,%g1 + ta 8 + nop + ta 1 + nop"); + } +} + +int +setitimer(int which, const struct itimerval *value, struct itimerval *ovalue) +{ + asm(" or %g0, 158, %g1 + ta 8 + nop"); +} + + + +long +sbrk (unsigned long amt) +{ + extern char _end; + static char *ptr = 0; + char *res; + if (ptr == 0) + ptr = &_end; + if (amt == 0) + return (long)ptr; + + if (((long)ptr) % 8) + ptr = ptr + (8 - (((long)(ptr)) % 8)); + res = ptr; + ptr += amt; + return (long)res; +} + +#ifdef TARGET_CPU_SPARC64 +long +_sbrk_r (void *foo, unsigned long amt) +{ + return sbrk(amt); +} + +long +_fstat_r (void *foo, void *bar, void *baz) +{ + return -1; +} + +long +_brk_r (void *foo) +{ + return sbrk(0); +} + +int +_open_r (char *filename, int mode) +{ + return open (filename, mode); +} + +int +_close_r (int fd) +{ + return close(fd); +} +#endif + +int +close (int fd) +{ + return 0; +} + +int +fstat(int des,void *buf) +{ + return -1; +} + +int +lseek(int des,unsigned long offset, int whence) +{ + return -1; +} + +int +isatty(int fd) +{ + return (fd < 3); +} + +int +kill (int pid, int signal) +{ + asm ("or %g0, 37, %g1 + ta 8 + nop"); +} + +int +getpid () +{ + return -1; +} + +int +getitimer (int which, struct itimerval *value) +{ + asm ("or %g0, 157, %g1 + ta 8 + nop"); +} + +void +__install_signal_handler (void *func) +{ + asm ("mov %o0, %o1 + mov %g0, %o0 + or %g0, 48, %g1 + ta 8 + nop"); +} + +int +gettimeofday (struct timeval *tp, struct timezone *tzp) +{ + asm ("or %g0, 156, %g1 + ta 8 + nop"); +} + +int +stime (long *seconds) +{ + asm ("or %g0, 25, %g1 + ta 8 + nop"); +} + +int +add_mapping (long vma, long pma, long size) +{ + asm ("or %g0, 115, %g1 + ta 8 + nop"); +} + +int +remove_mapping (long vma, long vma_end) +{ + asm ("or %g0, 117, %g1 + ta 8 + nop"); +} + +int +open (char *filename, int mode) +{ + return -1; +} + +void * +__getProgramArgs (int *argv) +{ + int *res; + + /* 184 is tsolsys under solaris; bad juju */ + asm ("mov %1, %%o0 + or %%g0, 184, %%g1 + ta 8 + nop + mov %%o0, %0" : "=r" (res) : "r" (argv): "g1"); + return res; +} diff --git a/libgloss/sparc/cygmon-sparc64-ld.src b/libgloss/sparc/cygmon-sparc64-ld.src new file mode 100644 index 0000000..efa0da1 --- /dev/null +++ b/libgloss/sparc/cygmon-sparc64-ld.src @@ -0,0 +1,159 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(start) +OUTPUT_ARCH(TARGET_OBJ_FORMAT) +SEARCH_DIR(.) +STARTUP(cygmon-crt0.o) +GROUP(cygmon-salib.o -lc -lgcc -lc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 1M; +_RAM_START = 0x4000; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Setup the standard memory map. The stack grows down towards low memory. + */ +MEMORY +{ + ram : ORIGIN = 0x4000, LENGTH = 1M +} + +__stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + CREATE_OBJECT_SYMBOLS + *(.text) + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + *(.init) + *(.lit) + *(.rodata) + *(.shdata) + *(.eh_frame) + *(.gnu.linkonce.t*) + *(.gnu.linkonce.r*) + *(.gcc_except_table) + *(.fini) + _etext = .; + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + *(.gnu.linkonce.d*) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/cygmon.ld.src b/libgloss/sparc/cygmon.ld.src new file mode 100644 index 0000000..bf06825 --- /dev/null +++ b/libgloss/sparc/cygmon.ld.src @@ -0,0 +1,195 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(start) +OUTPUT_ARCH(TARGET_OBJ_FORMAT) +SEARCH_DIR(.) +STARTUP(cygmon-crt0.o) +GROUP(cygmon-salib.o -lc -lgcc -lc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 1M; +_RAM_START = TARGET_RAM_START; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Setup the standard memory map. The stack grows down towards low memory. + */ +MEMORY +{ + ram : ORIGIN = TARGET_RAM_START, LENGTH = 1M +} + +__stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + CREATE_OBJECT_SYMBOLS + *(.text) + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + LONG(0) + __DTOR_END__ = .; + *(.init) + *(.lit) + *(.rodata) + *(.shdata) + *(.eh_frame) + *(.gnu.linkonce.t*) + *(.gnu.linkonce.r*) + *(.gcc_except_table) + *(.fini) + _etext = .; + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + *(.gnu.linkonce.d*) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } +/* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ +/* DWARF 1 */ + .debug 0 (NOLOAD) : + { + [ .debug ] + } + .line 0 (NOLOAD) : + { + [ .line ] + } +/* GNU DWARF 1 extensions */ + .debug_srcinfo 0 (NOLOAD) : + { + [ .debug_srcinfo ] + } + .debug_sfnames 0 (NOLOAD) : + { + [ .debug_sfnames ] + } +/* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 (NOLOAD) : + { + [ .debug_aranges ] + } + .debug_pubnames 0 (NOLOAD) : + { + [ .debug_pubnames ] + } +/* DWARF 2 */ + .debug_info 0 (NOLOAD) : + { + [ .debug_info ] + } + .debug_abbrev 0 (NOLOAD) : + { + [ .debug_abbrev ] + } + .debug_line 0 (NOLOAD) : + { + [ .debug_line ] + } + .debug_frame 0 (NOLOAD) : + { + [ .debug_frame ] + } + .debug_str 0 (NOLOAD) : + { + [ .debug_str ] + } + .debug_loc 0 (NOLOAD) : + { + [ .debug_loc ] + } + .debug_macinfo 0 (NOLOAD) : + { + [ .debug_macinfo ] + } +} diff --git a/libgloss/sparc/dtor.C b/libgloss/sparc/dtor.C new file mode 100644 index 0000000..abde4f1 --- /dev/null +++ b/libgloss/sparc/dtor.C @@ -0,0 +1,25 @@ +#include <stdio.h> + +extern "C" void print (char *, ...); + +class foo +{ +public: + foo () { print ("ctor\n"); } + ~foo () { print ("dtor\n"); } +}; + +foo x; + +main () +{ + outbyte ('&'); + outbyte ('@'); + outbyte ('$'); + outbyte ('%'); + print ("FooBar\r\n"); + + /* whew, we made it */ + print ("\r\nDone...\r\n"); +/* fflush(stdout); */ +} diff --git a/libgloss/sparc/elfsim.ld b/libgloss/sparc/elfsim.ld new file mode 100644 index 0000000..d1831be --- /dev/null +++ b/libgloss/sparc/elfsim.ld @@ -0,0 +1,202 @@ +/* Linker script for running ELF programs in the Sparc simulator */ + +/* OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparcle") */ +/* OUTPUT_FORMAT("elf32-sparc") */ +OUTPUT_ARCH(sparc) +STARTUP(traps.o) +INPUT(erc32-crt0.o) +ENTRY(_trap_table) +GROUP(-lc -lerc32 -lgcc) /* -lerc32 used to be -lsim */ + +SEARCH_DIR(.) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +/* + * User modifiable values: + * + * _CLOCK_SPEED in Mhz (used to program the counter/timers) + * + * _PROM_SIZE size of PROM (permissible values are 4K, 8K, 16K + * 32K, 64K, 128K, 256K, and 512K) + * _RAM_SIZE size of RAM (permissible values are 256K, 512K, + * 1MB, 2Mb, 4Mb, 8Mb, 16Mb, and 32Mb) + * + * These symbols are only used in assembler code, so they only need to + * be listed once. They should always be refered to without SYM(). + */ + +_CLOCK_SPEED = 10; + +_PROM_SIZE = 4M; +_RAM_SIZE = 256K; + +_RAM_START = 0x02000000; +_RAM_END = _RAM_START + _RAM_SIZE; +_STACK_SIZE = (16 * 1024); +_PROM_START = 0x00000000; +_PROM_END = _PROM_START + _PROM_SIZE; + + +/* + * Base address of the on-CPU peripherals + */ + +_ERC32_MEC = 0x01f80000; + +/* + * Setup the memory map for the SIS simulator. + * stack grows up towards low memory. + */ + +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 4M + ram (rwx) : ORIGIN = 0x02000000, LENGTH = 2M +} + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +SECTIONS +{ + .text : + { + _stext = .; + PROVIDE (stext = .); + __EH_FRAME_BEGIN__ = .; + *(.text) + _etext = .; + PROVIDE (etext = .); + + /* For a.out. */ + CONSTRUCTORS + + /* For ELF. */ + __CTOR_LIST__ = .; + LONG(-1) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG(-1) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + LONG(0) + __DTOR_END__ = .; + + *(.init) + *(.lit) + *(.rodata) + *(.shdata) + *(.eh_frame) + *(.gnu.linkonce.t*) + *(.gnu.linkonce.r*) + *(.gcc_except_table) + *(.fini) + + _endtext = .; + PROVIDE(endtext = .); + } > ram + + .shbss SIZEOF(.text) + ADDR(.text) : + { + *(.shbss) + } + + .talias : { } > ram + + .data : + { + _sdata = .; + PROVIDE (sdata = .); + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + _edata = .; + PROVIDE (edata = .); + } > ram + + .bss SIZEOF(.data) + ADDR(.data) : + { + _sbss = . ; + PROVIDE (sbss = . ); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + _ebss = .; + PROVIDE (ebss = .); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + PROVIDE (end = ALIGN(0x8)); + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/erc32-crt0.S b/libgloss/sparc/erc32-crt0.S new file mode 100644 index 0000000..8f8b1ea --- /dev/null +++ b/libgloss/sparc/erc32-crt0.S @@ -0,0 +1,75 @@ +/* + * This is based on the file srt0.s provided with the binary + * distribution of the SPARC Instruction Simulator (SIS) found + * at ftp://ftp.estec.esa.nl/pub/ws/wsd/erc32. + */ + +#include "asm.h" + + .data + .align 8 +SYM(environ): + .long 0 + + .text + + .globl SYM(start) +SYM(start): + sethi %hi(__stack), %g1 + or %g1,%lo(__stack),%g1 + mov %g1, %sp ! set the stack pointer + mov %sp, %fp + + /* clear the bss */ + sethi %hi(__bss_start),%g2 + or %g2,%lo(__bss_start),%g2 ! start of bss + sethi %hi(_end),%g3 + or %g3,%lo(_end),%g3 ! end of bss + mov %g0,%g1 ! so std has two zeros +zerobss: + std %g0,[%g2] + add %g2,8,%g2 + cmp %g2,%g3 + bleu,a zerobss + nop + + /* move data segment to proper location */ + +#if 0 +relocd: + set (_endtext),%g2 ! g2 = start of data in aout file + set (_environ),%g4 ! g4 = start of where data should go + set (_edata),%g3 ! g3 = end of where data should go + subcc %g3, %g4, %g5 ! g5 = length of data + + subcc %g4, %g2, %g0 ! need to relocate data ? + ble initok + ld [%g4], %g6 + subcc %g6, 1, %g0 + be initok +mvdata: + subcc %g5, 8, %g5 + ldd [%g2 + %g5], %g6 + bg mvdata + std %g6, [%g4 + %g5] + +initok: +#endif + + call SYM(__fix_ctors) + nop + call SYM(main) + nop + + /* call exit from the C library so atexit gets called, and the + * C++ destructors get run. This calls our exit routine below * when it's done. + */ + call SYM(exit) + nop + + .globl SYM(_exit) +SYM(_exit): + set 0xdeadd00d, %o1 ! Magic number for simulator. + ta 0 ! Halt if _main returns ... + nop + diff --git a/libgloss/sparc/erc32-io.c b/libgloss/sparc/erc32-io.c new file mode 100644 index 0000000..082d9f9 --- /dev/null +++ b/libgloss/sparc/erc32-io.c @@ -0,0 +1,47 @@ +#define USE_PORT_A + +#define RXADATA (int *) 0x01F800E0 +#define RXBDATA (int *) 0x01F800E4 +#define RXSTAT (int *) 0x01F800E8 + +void +outbyte (int c) +{ + volatile int *rxstat; + volatile int *rxadata; + int rxmask; + + rxstat = RXSTAT; +#ifdef USE_PORT_A + rxadata = RXADATA; + rxmask = 6; +#else + rxadata = RXBDATA; + rxmask = 0x60000; +#endif + + while ((*rxstat & rxmask) == 0); + + *rxadata = c; +} + +int +inbyte (void) +{ + volatile int *rxstat; + volatile int *rxadata; + int rxmask; + + rxstat = RXSTAT; +#ifdef USE_PORT_A + rxadata = RXADATA; + rxmask = 1; +#else + rxadata = RXBDATA; + rxmask = 0x10000; +#endif + + while ((*rxstat & rxmask) == 0); + + return *rxadata; +} diff --git a/libgloss/sparc/erc32-stub.c b/libgloss/sparc/erc32-stub.c new file mode 100644 index 0000000..71a65b2 --- /dev/null +++ b/libgloss/sparc/erc32-stub.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 1996 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. + */ + +#include <string.h> +#include <signal.h> +#include "debug.h" +#include "asm.h" +#include "slite.h" + +extern unsigned long rdtbr(); +extern struct trap_entry fltr_proto; +extern void trap_low(); +exception_t default_trap_hook = trap_low; +void target_reset(); +void flush_i_cache(); +char *target_read_registers(unsigned long *); +char *target_write_registers(unsigned long *); +char *target_dump_state(unsigned long *); + +#define NUMREGS 72 + +/* Number of bytes of registers. */ +#define NUMREGBYTES (NUMREGS * 4) + +enum regnames {G0, G1, G2, G3, G4, G5, G6, G7, + O0, O1, O2, O3, O4, O5, SP, O7, + L0, L1, L2, L3, L4, L5, L6, L7, + I0, I1, I2, I3, I4, I5, FP, I7, + + F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR }; + +/* + * Each entry in the trap vector occupies four words, typically a jump + * to the processing routine. + */ +struct trap_entry { + unsigned sethi_filler:10; + unsigned sethi_imm22:22; + unsigned jmpl_filler:19; + unsigned jmpl_simm13:13; + unsigned long filler[2]; +}; + +/* + * This table contains the mapping between SPARC hardware trap types, and + * signals, which are primarily what GDB understands. It also indicates + * which hardware traps we need to commandeer when initializing the stub. + */ +struct trap_info hard_trap_info[] = { + {1, SIGSEGV}, /* instruction access error */ + {2, SIGILL}, /* privileged instruction */ + {3, SIGILL}, /* illegal instruction */ + {4, SIGEMT}, /* fp disabled */ + {36, SIGEMT}, /* cp disabled */ + {7, SIGBUS}, /* mem address not aligned */ + {9, SIGSEGV}, /* data access exception */ + {10, SIGEMT}, /* tag overflow */ + {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */ + {0, 0} /* Must be last */ +}; + +extern struct trap_entry fltr_proto; +void +exception_handler (int tt, unsigned long routine) +{ + struct trap_entry *tb; /* Trap vector base address */ + + DEBUG (1, "Entering exception_handler()"); + if (tt != 256) { + tb = (struct trap_entry *) (rdtbr() & ~0xfff); + } else { + tt = 255; + tb = (struct trap_entry *) 0; + } + + tb[tt] = fltr_proto; + + tb[tt].sethi_imm22 = routine >> 10; + tb[tt].jmpl_simm13 = routine & 0x3ff; + + DEBUG (1, "Leaving exception_handler()"); +} + +/* + * This is so we can trap a memory fault when reading or writing + * directly to memory. + */ +void +set_mem_fault_trap(enable) + int enable; +{ + extern void fltr_set_mem_err(); + + DEBUG (1, "Entering set_mem_fault_trap()"); + + mem_err = 0; + + if (enable) + exception_handler(9, (unsigned long)fltr_set_mem_err); + else + exception_handler(9, (unsigned long)trap_low); + + DEBUG (1, "Leaving set_mem_fault_trap()"); +} + +/* + * This function does all command procesing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ +extern void breakinst(); + +void +handle_exception (registers) + unsigned long *registers; +{ + int sigval; + + /* First, we must force all of the windows to be spilled out */ + + DEBUG (1, "Entering handle_exception()"); + +/* asm("mov %g0, %wim ; nop; nop; nop"); */ + asm(" save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + restore + restore + restore + restore + restore + restore + restore + restore +"); + + if (registers[PC] == (unsigned long)breakinst) { + registers[PC] = registers[NPC]; + registers[NPC] += 4; + } + + /* get the last know signal number from the trap register */ + sigval = computeSignal((registers[TBR] >> 4) & 0xff); + + /* call the main command processing loop for gdb */ + gdb_event_loop (sigval, registers); +} + +/* + * This function will generate a breakpoint exception. It is used at the + * beginning of a program to sync up with a debugger and can be used + * otherwise as a quick means to stop program execution and "break" into + * the debugger. + */ +void +breakpoint() +{ + DEBUG (1, "Entering breakpoint()"); + + if (!initialized) + return; + + asm(" .globl " STRINGSYM(breakinst) " + " STRINGSYM(breakinst) ": ta 128+1 + nop + nop + "); +} + +/* + * This is just a test vector for debugging excpetions. + */ +void +bad_trap(tt) +int tt; +{ + print ("Got a bad trap #"); + outbyte (tt); + outbyte ('\n'); + asm("ta 0 + nop + nop + "); +} + +/* + * This is just a test vector for debugging excpetions. + */ +void +soft_trap(tt) +int tt; +{ + print ("Got a soft trap #"); + outbyte (tt); + outbyte ('\n'); + asm("ta 0 + nop + nop + "); +} + +/* + * Flush the instruction cache. We need to do this for the debugger stub so + * that breakpoints, et. al. become visible to the instruction stream after + * storing them in memory. + * + * For the sparclite, we need to do something here, but for a standard + * sparc (which SIS simulates), we don't. + */ + +void +flush_i_cache () +{ +} + +/* + * This will reset the processor, so we never return from here. + */ +void +target_reset() +{ + asm ("call 0 + nop "); +} + +/* + * g - read registers. + * no params. + * returns a vector of words, size is NUM_REGS. + */ +char * +target_read_registers(unsigned long *registers) +{ + char *ptr; + unsigned long *sp; + + DEBUG (1, "In target_read_registers()"); + + ptr = packet_out_buf; + ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ + ptr = mem2hex((unsigned char *)(sp + 0), ptr, 16 * 4, 0); /* L & I regs */ + memset(ptr, '0', 32 * 8); /* Floating point */ + mem2hex((char *)®isters[Y], + ptr + 32 * 4 * 2, + 8 * 4, + 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + return (ptr); +} + +/* + * G - write registers. + * param is a vector of words, size is NUM_REGS. + * returns an OK or an error number. + */ +char * +target_write_registers(unsigned long *registers) +{ + unsigned char *ptr; + unsigned long *sp; + unsigned long *newsp, psr; + + DEBUG (1, "In target_write_registers()"); + + psr = registers[PSR]; + + ptr = &packet_in_buf[1]; + + hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ + hex2mem(ptr + 16 * 4 * 2, (unsigned char *)(sp + 0), 16 * 4, 0); /* L & I regs */ + hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], + 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + + /* + * see if the stack pointer has moved. If so, then copy the saved + * locals and ins to the new location. This keeps the window + * overflow and underflow routines happy. + */ + + newsp = (unsigned long *)registers[SP]; + if (sp != newsp) + sp = memcpy(newsp, sp, 16 * 4); + + /* Don't allow CWP to be modified. */ + + if (psr != registers[PSR]) + registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f); + + return (ptr); +} + +char * +target_dump_state(unsigned long *registers) +{ + int tt; /* Trap type */ + int sigval; + char *ptr; + unsigned long *sp; + + DEBUG (1, "In target_dump_state()"); + + sp = (unsigned long *)registers[SP]; + + tt = (registers[TBR] >> 4) & 0xff; + + /* reply to host that an exception has occurred */ + sigval = computeSignal(tt); + ptr = packet_out_buf; + + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + *ptr++ = hexchars[PC >> 4]; + *ptr++ = hexchars[PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((unsigned char *)®isters[PC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[FP >> 4]; + *ptr++ = hexchars[FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((unsigned char *)(sp + 8 + 6), ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = hexchars[SP >> 4]; + *ptr++ = hexchars[SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((unsigned char *)&sp, ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[NPC >> 4]; + + return (packet_out_buf); +} + +void +write_pc(unsigned long *registers, unsigned long addr) +{ + DEBUG (1, "In write_pc"); + + registers[PC] = addr; + registers[NPC] = addr + 4; +} diff --git a/libgloss/sparc/erc32.ld b/libgloss/sparc/erc32.ld new file mode 100644 index 0000000..179dcc0 --- /dev/null +++ b/libgloss/sparc/erc32.ld @@ -0,0 +1,146 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +STARTUP(traps.o) +INPUT(sim-crt0.o) +OUTPUT_ARCH(sparc) +SEARCH_DIR(.) +__DYNAMIC = 0; +GROUP(-lc -lsim -lgcc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +/* + * User modifiable values: + * + * _CLOCK_SPEED in Mhz (used to program the counter/timers) + * + * _PROM_SIZE size of PROM (permissible values are 4K, 8K, 16K + * 32K, 64K, 128K, 256K, and 512K) + * _RAM_SIZE size of RAM (permissible values are 256K, 512K, + * 1MB, 2Mb, 4Mb, 8Mb, 16Mb, and 32Mb) + * + * These symbols are only used in assembler code, so they only need to + * be listed once. They should always be refered to without SYM(). + */ + +_CLOCK_SPEED = 10; + +_PROM_SIZE = 4M; +_RAM_SIZE = 2M; + +_RAM_START = 0x02020000; +_RAM_END = _RAM_START + _RAM_SIZE; +_STACK_SIZE = (16 * 1024); +_PROM_START = 0x00000000; +_PROM_END = _PROM_START + _PROM_SIZE; + + +/* + * Base address of the on-CPU peripherals + */ + +_ERC32_MEC = 0x01f80000; + +/* + * Setup the memory map for the SIS simulator. + * stack grows up towards low memory. + */ +/* +MEMORY +{ + rom : ORIGIN = 0x00000000, LENGTH = 4M + ram (rwx) : ORIGIN = 0x02000000, LENGTH = 2M +} +*/ + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +SECTIONS +{ + .text 0x02000000 : { + stext = .; + _stext = .; + *(.text) + _etext = .; + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + *(.lit) + *(.shdata) + _endtext = .; + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : + { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : + { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } +} diff --git a/libgloss/sparc/ex930.ld b/libgloss/sparc/ex930.ld new file mode 100644 index 0000000..b501b2e --- /dev/null +++ b/libgloss/sparc/ex930.ld @@ -0,0 +1,160 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(_start) +STARTUP(crt0.o) +OUTPUT_ARCH(sparc) +SEARCH_DIR(.) +__DYNAMIC = 0; +GROUP (-lc -lslite930 -lgcc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 2M; +_RAM_START = 0x40000000; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Base address of the on-CPU peripherals. This is for compatability + * with the simulator. + */ + +_ERC32_MEC = 0x0; + +/* + * Setup the memory map of the MB86931-EB Board (ex931) + * stack grows down towards low memory. + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x40000000, LENGTH = 2M +} + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + CREATE_OBJECT_SYMBOLS + *(.text) + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + _etext = .; + *(.lit) + *(.shdata) + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/ex931.ld b/libgloss/sparc/ex931.ld new file mode 100644 index 0000000..26ffb4d --- /dev/null +++ b/libgloss/sparc/ex931.ld @@ -0,0 +1,160 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(_start) +STARTUP(crt0.o) +OUTPUT_ARCH(sparc) +SEARCH_DIR(.) +__DYNAMIC = 0; +GROUP (-lc -lslite931 -lgcc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 2M; +_RAM_START = 0x40000000; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Base address of the on-CPU peripherals. This is for compatability + * with the simulator. + */ + +_ERC32_MEC = 0x0; + +/* + * Setup the memory map of the MB86931-EB Board (ex931) + * stack grows down towards low memory. + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x40000000, LENGTH = 2M +} + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + CREATE_OBJECT_SYMBOLS + *(.text) + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + _etext = .; + *(.lit) + *(.shdata) + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/ex934.ld b/libgloss/sparc/ex934.ld new file mode 100644 index 0000000..7d1d5ed --- /dev/null +++ b/libgloss/sparc/ex934.ld @@ -0,0 +1,160 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(_start) +STARTUP(crt0.o) +OUTPUT_ARCH(sparc) +SEARCH_DIR(.) +__DYNAMIC = 0; +GROUP (-lc -lslite934 -lgcc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 2M; +_RAM_START = 0x40010000; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Base address of the on-CPU peripherals. This is for compatability + * with the simulator. + */ + +_ERC32_MEC = 0x0; + +/* + * Setup the memory map of the MB86931-EB Board (ex931) + * stack grows down towards low memory. + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x40010000, LENGTH = 2M +} + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + CREATE_OBJECT_SYMBOLS + *(.text) + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + _etext = .; + *(.lit) + *(.shdata) + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/fixctors.c b/libgloss/sparc/fixctors.c new file mode 100644 index 0000000..484023c --- /dev/null +++ b/libgloss/sparc/fixctors.c @@ -0,0 +1,54 @@ +/* Code to byte-swap static constructor/destructor tables on + broken a.out little-endian targets. The startup code should call + __fix_ctors just before calling main. It is safe to use on non-broken + or big-endian targets. */ + +extern long __CTOR_LIST__[]; +extern long __DTOR_LIST__[]; + +static void +byte_swap (long *entry) +{ + unsigned char *p = (unsigned char *)entry; + unsigned char tmp; + + tmp = p[0]; + p[0] = p[3]; + p[3] = tmp; + tmp = p[1]; + p[1] = p[2]; + p[2] = tmp; +} + +static void +fix_table (long *table) +{ + long len = table[0]; + + /* The heuristic for deciding if a table is broken is to examine + the word at the start of the table, which contains the number + of function pointers immediately following. If the low word + is zero, and the high word is non-zero, it's very likely that + it is byte-swapped. This test will fail if the program has + an exact multiple of 64K static constructors or destructors, a very + unlikely situation. */ + if ((len & 0xffff) == 0 && (len & 0xffff0000) != 0) + { + + /* The table looks broken. Byte-swap all the words in the table, up + to a NULL entry, which marks the end of the table. */ + do + { + byte_swap (table); + table++; + } + while (*table); + } +} + +void +__fix_ctors (void) +{ + fix_table (__CTOR_LIST__); + fix_table (__DTOR_LIST__); +} diff --git a/libgloss/sparc/libsys/Makefile.in b/libgloss/sparc/libsys/Makefile.in new file mode 100644 index 0000000..f3a036f --- /dev/null +++ b/libgloss/sparc/libsys/Makefile.in @@ -0,0 +1,167 @@ +# Makefile for libgloss/sparc/libsys +# Copyright (c) 1996 Cygnus Support. +# All rights reserved. +# +# Redistribution and use in source and binary forms are permitted +# provided that the above copyright notice and this paragraph are +# duplicated in all such forms and that any documentation, +# advertising materials, and other materials related to such +# distribution and use acknowledge that the software was developed +# at Cygnus Support, Inc. Cygnus Support, Inc. may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +VPATH = @srcdir@ +srcdir = @srcdir@ +objdir = . +srcroot = $(srcdir)/../.. +objroot = $(objdir)/../.. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ + +bindir = @bindir@ +libdir = @libdir@ +tooldir = $(exec_prefix)/$(target_alias) + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +SHELL = /bin/sh + +CC = @CC@ + +AS = @AS@ +AR = @AR@ +LD = @LD@ +RANLIB = @RANLIB@ + +# _r.o is for the reentrant syscall stubs. +# The .S_r.o/.c_r.o rules are from host/any. + +.SUFFIXES: .c .S .o _r.o + +.S_r.o: + $(CC) $(CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS) -DREENT $(INCLUDES) -c $< -o $@ +.c_r.o: + $(CC) $(CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS) -DREENT $(INCLUDES) -c $< -o $@ + +# CFILES_R, SFILES_R, and TEMPLATE_SFILES_R define those system calls that are +# needed by the ANSI C part of newlib when REENTRANT_SYSCALLS_PROVIDED is +# defined. + +CFILES = isatty.c + +CFILES_R = + +SFILES = cerror.S _exit.S + +SFILES_R = sbrk.S + +# List of files built from template.S (with an '_' suffix). + +TEMPLATE_SFILES = chdir_ lstat_ + +TEMPLATE_SFILES_R = close_ fstat_ getpid_ kill_ \ + lseek_ open_ read_ stat_ unlink_ write_ + +# If newlib defines REENTRANT_SYSCALLS_PROVIDED, then these are used as well. +REENTRANT_OFILES = $(SFILES_R:.S=_r.o) $(TEMPLATE_SFILES_R:_=_r.o) \ + $(CFILES_R:.c=_r.o) + +OFILES = $(SFILES:.S=.o) $(SFILES_R:.S=.o) \ + $(TEMPLATE_SFILES:_=.o) $(TEMPLATE_SFILES_R:_=.o) \ + $(CFILES:.c=.o) $(CFILES_R:.c=.o) \ + $(REENTRANT_OFILES) + +#### Host specific Makefile fragment comes in here. +@host_makefile_frag@ + +all: libsys.a libsys-crt0.o + +libsys.a: $(OFILES) + rm -f $@ + $(AR) $(AR_FLAGS) $@ $(OFILES) + +install: + $(INSTALL_DATA) libsys-crt0.o $(tooldir)/lib/libsys-crt0.o + $(INSTALL_DATA) libsys.a $(tooldir)/lib/libsys.a + +doc: + +.PHONY: info install-info clean-info +info: +install-info: +clean-info: + +clean mostlyclean: + rm -f *.o *.a *.s stamp-srcs + +distclean maintainer-clean realclean: clean + rm -f Makefile config.status + +Makefile: Makefile.in config.status @host_makefile_frag_path@ + $(SHELL) config.status + +config.status: configure + $(SHELL) config.status --recheck + +stamp-srcs: Makefile template.S template_r.S + for f in $(TEMPLATE_SFILES:_=) ; \ + do \ + $(CC) -E -Dfunc=$$f \ + $(CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS) $(INCLUDES) \ + $(srcdir)/template.S >$$f.S ; \ + done + for f in $(TEMPLATE_SFILES_R:_=) ; \ + do \ + $(CC) -E -Dfunc=$$f \ + $(CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) $(NEWLIB_CFLAGS) $(INCLUDES) \ + $(srcdir)/template_r.S | sed -e 's/^_/#/' >$$f.S ; \ + done + touch stamp-srcs + +# Make a dependency for each file built from a template. + +$(TEMPLATE_SFILES:_=.S) $(TEMPLATE_SFILES_R:_=.S): stamp-srcs + +# To support SunOS broken VPATH (sigh). + +_exit.o: _exit.S +cerror.o: cerror.S +chdir.o: chdir.S +close.o: close.S +fstat.o: fstat.S +getpid.o: getpid.S +isatty.o: isatty.c +kill.o: kill.S +libsys-crt0.o: libsys-crt0.S +lseek.o: lseek.S +lstat.o: lstat.S +open.o: open.S +read.o: read.S +sbrk.o: sbrk.S +stat.o: stat.S +write.o: write.S + +# Reentrant versions ... +# These are all needed to support the ANSI C library routines. + +close_r.o: close.S +fstat_r.o: fstat.S +getpid_r.o: getpid.S +kill_r.o: kill.S +lseek_r.o: lseek.S +open_r.o: open.S +read_r.o: read.S +sbrk_r.o: sbrk.S +stat_r.o: stat.S +unlink_r.o: unlink.S +write_r.o: write.S diff --git a/libgloss/sparc/libsys/_exit.S b/libgloss/sparc/libsys/_exit.S new file mode 100644 index 0000000..52c5c14 --- /dev/null +++ b/libgloss/sparc/libsys/_exit.S @@ -0,0 +1,14 @@ +! _exit() system call + +#include "syscallasm.h" + + TEXT_SECTION + ALIGN (4) + GLOBAL (ASM_SYMBOL (_exit)) +ASM_SYMBOL (_exit): + mov SYS_exit,%g1 + ta SYSCALL_TRAP + +! If that returns (yikes!), try an illegal insn ... + + WORD (0)
\ No newline at end of file diff --git a/libgloss/sparc/libsys/cerror.S b/libgloss/sparc/libsys/cerror.S new file mode 100644 index 0000000..8ad99c2 --- /dev/null +++ b/libgloss/sparc/libsys/cerror.S @@ -0,0 +1,47 @@ +! Set errno. +! This function is called by all the syscall stubs. +! +! FIXME: We assume errno is the first member of struct _reent. +! Not sure what to do about this. + +#include "syscallasm.h" + + DATA_SECTION + ALIGN (4) + GLOBAL (ASM_SYMBOL (errno)) ! FIXME: ASM_PRIVATE_SYMBOL ? +ASM_SYMBOL (errno): + WORD (0) + + TEXT_SECTION + ALIGN (4) + + GLOBAL (ASM_PRIVATE_SYMBOL (cerror)) +ASM_PRIVATE_SYMBOL (cerror): + sethi %hi (ASM_SYMBOL (errno)),%g1 + st %o0,[%g1+%lo (ASM_SYMBOL (errno))] + jmpl %o7+8,%g0 + mov -1,%o0 + + GLOBAL (ASM_PRIVATE_SYMBOL (cerror_r)) +ASM_PRIVATE_SYMBOL (cerror_r): + st %o0,[%o1] + jmpl %o7+8,%g0 + mov -1,%o0 + +! Since all system calls need this file, we put various state globals +! here as well. + + DATA_SECTION + +! CURBRK contains the current top of allocated space. +! END is a private symbol in svr4, but a public one in sunos4. +! FIXME: CURBRK is 4 bytes for now. + + ALIGN (4) + GLOBAL (ASM_PRIVATE_SYMBOL (curbrk)) +ASM_PRIVATE_SYMBOL (curbrk): +#ifdef SVR4 + WORD (ASM_PRIVATE_SYMBOL (end)) +#else + WORD (ASM_SYMBOL (end)) +#endif diff --git a/libgloss/sparc/libsys/configure b/libgloss/sparc/libsys/configure new file mode 100755 index 0000000..3702cce --- /dev/null +++ b/libgloss/sparc/libsys/configure @@ -0,0 +1,991 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.10 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.10" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=libsys-crt0.S + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +if test "$srcdir" = "." ; then + mdir=`echo "${with_multisubdir}/" \ + | sed -e 's,\([^/][^/]*\),..,g' -e 's,^/$,,'` + ac_aux_dir= +for ac_dir in ${mdir}../../../.. $srcdir/${mdir}../../../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in ${mdir}../../../.. $srcdir/${mdir}../../../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +else + ac_aux_dir= +for ac_dir in ${srcdir}/../../.. $srcdir/${srcdir}/../../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in ${srcdir}/../../.. $srcdir/${srcdir}/../../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# 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 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # 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 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:707: \"$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 +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 +if test $ac_cv_prog_gcc = yes; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_gcc_g=yes +else + ac_cv_prog_gcc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 + if test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +AS=${AS-as} + +AR=${AR-ar} + +LD=${LD-ld} + +# 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 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +host_makefile_frag=${srcdir}/../../config/default.mh + +host_makefile_frag_path=$host_makefile_frag + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \ + >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.10" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC@%$CC%g +s%@AS@%$AS%g +s%@AR@%$AR%g +s%@LD@%$LD%g +s%@RANLIB@%$RANLIB%g +s%@host_makefile_frag_path@%$host_makefile_frag_path%g +/@host_makefile_frag@/r $host_makefile_frag +s%@host_makefile_frag@%%g + +CEOF +EOF +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust relative srcdir, etc. for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file +fi; done +rm -f conftest.subs + + + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/libgloss/sparc/libsys/configure.in b/libgloss/sparc/libsys/configure.in new file mode 100644 index 0000000..cf3f496 --- /dev/null +++ b/libgloss/sparc/libsys/configure.in @@ -0,0 +1,50 @@ +# Configure.in for libgloss/sparc/libsys +# Copyright (c) 1996 Cygnus Support +# All rights reserved. +# +# Redistribution and use in source and binary forms are permitted +# provided that the above copyright notice and this paragraph are +# duplicated in all such forms and that any documentation, +# advertising materials, and other materials related to such +# distribution and use acknowledge that the software was developed +# at Cygnus Support, Inc. Cygnus Support, Inc. may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.5)dnl +AC_INIT(libsys-crt0.S) + +if test "$srcdir" = "." ; then + mdir=`echo "${with_multisubdir}/" \ + | sed -e 's,\([[^/]][[^/]]*\),..,g' -e 's,^/$,,'` + AC_CONFIG_AUX_DIR(${mdir}../../../..) +else + AC_CONFIG_AUX_DIR(${srcdir}/../../..) +fi + +AC_PROG_INSTALL + +AC_PROG_CC +AS=${AS-as} +AC_SUBST(AS) +AR=${AR-ar} +AC_SUBST(AR) +LD=${LD-ld} +AC_SUBST(LD) +AC_PROG_RANLIB + +host_makefile_frag=${srcdir}/../../config/default.mh + +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) + +AC_OUTPUT(Makefile) diff --git a/libgloss/sparc/libsys/isatty.c b/libgloss/sparc/libsys/isatty.c new file mode 100644 index 0000000..3c64647 --- /dev/null +++ b/libgloss/sparc/libsys/isatty.c @@ -0,0 +1,17 @@ +/* isatty.c */ + +/* Dumb implementation so programs will at least run. */ + +#include <sys/stat.h> + +int +isatty (int fd) +{ + struct stat buf; + + if (fstat (fd, &buf) < 0) + return 0; + if (S_ISCHR (buf.st_mode)) + return 1; + return 0; +} diff --git a/libgloss/sparc/libsys/libsys-crt0.S b/libgloss/sparc/libsys/libsys-crt0.S new file mode 100644 index 0000000..ef1b29d --- /dev/null +++ b/libgloss/sparc/libsys/libsys-crt0.S @@ -0,0 +1,127 @@ +! C run time start off + +! This file supports: +! +! - both 32bit pointer and 64bit pointer environments (at compile time) +! - an imposed stack bias (of 2047) (at run time) +! - medium/low and medium/anywhere code models (at run time) + +! Initial stack setup: +! +! bottom of stack (higher memory address) +! ... +! text of environment strings +! text of argument strings +! envp[envc] = 0 (4/8 bytes) +! ... +! env[0] (4/8 bytes) +! argv[argc] = 0 (4/8 bytes) +! ... +! argv[0] (4/8 bytes) +! argc (4/8 bytes) +! register save area (64 bits by 16 registers = 128 bytes) +! top of stack (%sp) + +! Stack Bias: +! +! It is the responsibility of the o/s to set this up. +! We handle both a 0 and 2047 value for the stack bias. + +! Medium/Anywhere code model support: +! +! In this model %g4 points to the start of the data segment. +! The text segment can go anywhere, but %g4 points to the *data* segment. +! It is up to the compiler/linker to get this right. +! +! Since this model is statically linked the start of the data segment +! is known at link time. Eg: +! +! sethi %hh(data_start), %g1 +! sethi %lm(data_start), %g4 +! or %g1, %hm(data_start), %g1 +! or %g4, %lo(data_start), %g4 +! sllx %g1, 32, %g1 +! or %g4, %g1, %g4 +! +! FIXME: For now we just assume 0. + +! FIXME: if %g1 contains a non-zero value, atexit() should be invoked +! with this value. + +#include "syscallasm.h" + +#ifndef TARGET_PTR_SIZE +#define TARGET_PTR_SIZE 32 +#endif + + TEXT_SECTION + ALIGN (4) + GLOBAL (ASM_PRIVATE_SYMBOL (start)) +ASM_PRIVATE_SYMBOL (start): + clr %fp + +! We use %g4 even if the code model is Medium/Low (simplifies the code). + + clr %g4 ! Medium/Anywhere base reg + +! If there is a stack bias in effect, account for it in %g5. Then always +! add %g5 to stack references below. This way the code can be used with +! or without an imposed bias. + + andcc %sp, 1, %g5 + bnz,a .LHaveBias + mov 2047, %g5 +.LHaveBias: + add %sp, %g5, %sp + +#if TARGET_PTR_SIZE == 32 + ! FIXME: We apparently assume here that there is no reserved word. + ! This is probably correct, but try to verify it. + ld [%sp + 0x80], %o0 ! argc + add %sp, 0x84, %o1 ! argv + add %o0, 1, %o2 + sll %o2, 2, %o2 +#else /* TARGET_PTR_SIZE == 64 */ + ld [%sp + 0x8c], %o0 ! argc.lo + add %sp, 0x90, %o1 ! argv + add %o0, 1, %o2 + sll %o2, 3, %o2 +#endif + add %o1, %o2, %o2 ! envp + sethi %hi (ASM_SYMBOL (environ)), %o3 + or %o3, %lo (ASM_SYMBOL (environ)), %o3 +#if TARGET_PTR_SIZE == 32 + st %o2, [%o3 + %g4] +#else /* TARGET_PTR_SIZE == 64 */ + stx %o2, [%o3 + %g4] +#endif + +! Restore any stack bias before we call main() ... + + sub %sp, %g5, %sp + + GLOBAL (ASM_SYMBOL (main)) + call ASM_SYMBOL (main) + +! FIXME: Not sure if this is needed anymore. +#if TARGET_PTR_SIZE == 32 + sub %sp, 0x20, %sp ! room to push args +#else /* TARGET_PTR_SIZE == 64 */ + sub %sp, 0x30, %sp ! room to push args +#endif + + GLOBAL (ASM_SYMBOL (exit)) + call ASM_SYMBOL (exit) + nop + + GLOBAL (ASM_SYMBOL (_exit)) + call ASM_SYMBOL (_exit) + nop + + set SYS_exit, %g1 + ta SYSCALL_TRAP ! in case user redefines __exit + +! If all the above methods fail to terminate the program, try an illegal insn. +! If that does not work, the o/s is hosed more than we are. + + WORD (0) diff --git a/libgloss/sparc/libsys/sbrk.S b/libgloss/sparc/libsys/sbrk.S new file mode 100644 index 0000000..b862621 --- /dev/null +++ b/libgloss/sparc/libsys/sbrk.S @@ -0,0 +1,66 @@ +! sbrk() system call + +#include "syscallasm.h" + + TEXT_SECTION + ALIGN (4) +#ifdef REENT + GLOBAL (ASM_SYMBOL (_sbrk_r)) +ASM_SYMBOL (_sbrk_r): + mov %o0,%o5 + mov %o1,%o0 +#else + GLOBAL (ASM_SYMBOL (sbrk)) +ASM_SYMBOL (sbrk): +#endif + add %o0,7,%o0 + andn %o0,7,%o0 + sethi %hi (ASM_PRIVATE_SYMBOL (curbrk)),%o2 +#ifdef __sparc_v9__ + lduw [%o2+%lo (ASM_PRIVATE_SYMBOL (curbrk))],%o3 +#else + ld [%o2+%lo (ASM_PRIVATE_SYMBOL (curbrk))],%o3 +#endif + add %o3,7,%o3 + andn %o3,7,%o3 + add %o3,%o0,%o0 + mov %o0,%o4 + mov SYS_brk,%g1 + ta SYSCALL_TRAP + bcs err + nop + st %o4,[%o2+%lo (ASM_PRIVATE_SYMBOL (curbrk))] + jmpl %o7+8,%g0 + mov %o3,%o0 + +#ifdef REENT + GLOBAL (ASM_SYMBOL (_brk_r)) +ASM_SYMBOL (_brk_r): + mov %o0,%o5 + mov %o1,%o0 +#else + GLOBAL (ASM_SYMBOL (brk)) +ASM_SYMBOL (brk): +#endif + add %o0,7,%o0 + andn %o0,7,%o0 + mov %o0,%o2 + mov SYS_brk,%g1 + ta SYSCALL_TRAP + bcs err + nop + sethi %hi (ASM_PRIVATE_SYMBOL (curbrk)),%o3 + st %o2,[%o3+%lo (ASM_PRIVATE_SYMBOL (curbrk))] + retl + mov %g0,%o0 + +err: +#ifdef REENT + sethi %hi (ASM_PRIVATE_SYMBOL (cerror_r)),%g1 + or %g1,%lo (ASM_PRIVATE_SYMBOL (cerror_r)),%g1 +#else + sethi %hi (ASM_PRIVATE_SYMBOL (cerror)),%g1 + or %g1,%lo (ASM_PRIVATE_SYMBOL (cerror)),%g1 +#endif + jmpl %g1,%g0 + mov %o5,%o1 diff --git a/libgloss/sparc/libsys/syscall.h b/libgloss/sparc/libsys/syscall.h new file mode 100644 index 0000000..457fe3a --- /dev/null +++ b/libgloss/sparc/libsys/syscall.h @@ -0,0 +1,39 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +/* + * This file defines the minimal set of system calls needed + * by newlib for both sunos4 and solaris2. + * + * WARNING: This file can be included by assembler files. + */ + +/* Process control. */ +#define SYS_exit 1 +#define SYS_getpid 20 +#define SYS_kill 37 + +/* File stuff. */ +#define SYS_read 3 +#define SYS_write 4 +#define SYS_open 5 +#define SYS_close 6 +#define SYS_lseek 19 + +/* Memory stuff. */ +#define SYS_brk 17 + +/* Directory stuff. */ +#define SYS_unlink 10 +#define SYS_chdir 12 +#ifdef SVR4 +#define SYS_stat 18 +#define SYS_fstat 28 +#define SYS_lstat 88 +#else +#define SYS_stat 38 +#define SYS_fstat 62 +#define SYS_lstat 40 +#endif + +#endif /* _SYSCALL_H_ */ diff --git a/libgloss/sparc/libsys/syscallasm.h b/libgloss/sparc/libsys/syscallasm.h new file mode 100644 index 0000000..55f25cd --- /dev/null +++ b/libgloss/sparc/libsys/syscallasm.h @@ -0,0 +1,93 @@ +#ifndef _SYSCALLASM_H_ +#define _SYSCALLASM_H_ + +/* + * This file defines the system calls for SPARC for the assembler. + * Anything C-ish is not allowed in this file. + * C files should include syscall.h. + */ + +#include "syscall.h" + +/* Some macros for writing assember syscall stubs. */ + +#ifdef SVR4 +#define TEXT_SECTION .section ".text" +#define DATA_SECTION .section ".data" +#define ALIGN(x) .align x +#define GLOBAL(sym) .global sym +#define WORD(x) .long x +#define ASM_SYMBOL(name) name +#define ASM_PRIVATE_SYMBOL(name) _##name +#define SYSCALL_TRAP 8 +#else +#define TEXT_SECTION .text +#define DATA_SECTION .data +#define ALIGN(x) .align x +#define GLOBAL(sym) .global sym +#define WORD(x) .word x +#define ASM_SYMBOL(name) _##name +#define ASM_PRIVATE_SYMBOL(name) name +#define SYSCALL_TRAP 0 +#endif + +#define defsyscall(name, n) \ + TEXT_SECTION ; \ + ALIGN (4) ; \ + GLOBAL (ASM_SYMBOL (name)) ; \ +ASM_SYMBOL (name): \ + mov n,%g1 ; \ + ta SYSCALL_TRAP ; \ + bcc noerr ; \ + sethi %hi (ASM_PRIVATE_SYMBOL (cerror)),%g1 ; \ + or %g1,%lo (ASM_PRIVATE_SYMBOL (cerror)),%g1 ; \ + jmpl %g1+%g0,%g0 ; \ + nop ; \ +noerr: \ + jmpl %o7+8,%g0 ; \ + nop + +/* Support for reentrant syscalls. The "struct _reent *" arg is always the + the first one. After that we allow up to four additional args. We could + allow more, but that's all we need for now. + + It may seem inefficient to have the reent arg be the first one as it means + copying all the other args into place (as opposed to making the reent arg + the last one in which case there wouldn't be any copying). I chose a clean + design over an extra four instructions in a system call. All other + reentrant functions use the first arg this way. + ??? Of course this scheme breaks down if we need to support 6 or more args. + + And of course the system calls aren't *really* reentrant. The intent + is to exercise the reentrancy framework rather than provide/claim + real reentrancy for this port. +*/ + +#define defsyscall_r(name, n) \ + TEXT_SECTION ; \ + ALIGN (4) ; \ + GLOBAL (ASM_SYMBOL (name)) ; \ +ASM_SYMBOL (name): \ + mov n,%g1 ; \ + mov %o0,%o5 ; \ + mov %o1,%o0 ; \ + mov %o2,%o1 ; \ + mov %o3,%o2 ; \ + mov %o4,%o3 ; \ + ta SYSCALL_TRAP ; \ + bcc noerr ; \ + sethi %hi (ASM_PRIVATE_SYMBOL (cerror_r)),%g1 ; \ + or %g1,%lo (ASM_PRIVATE_SYMBOL (cerror_r)),%g1 ; \ + jmpl %g1+%g0,%g0 ; \ + mov %o5,%o1 ; \ +noerr: \ + jmpl %o7+8,%g0 ; \ + nop + +#define seterrno() \ + sethi %hi (ASM_PRIVATE_SYMBOL (cerror)),%g1 ; \ + or %g1,%lo (ASM_PRIVATE_SYMBOL (cerror)),%g1 ; \ + jmpl %g1+%g0,%g0 ; \ + nop + +#endif /* _SYSCALLASM_H_ */ diff --git a/libgloss/sparc/libsys/template.S b/libgloss/sparc/libsys/template.S new file mode 100644 index 0000000..e1b437b --- /dev/null +++ b/libgloss/sparc/libsys/template.S @@ -0,0 +1,14 @@ +/* system call template */ + +/* Lots of system calls are trivial functions, so we build their source files + from a template. New syscalls can be added simply by editing the + Makefile! + + Usage: Compile this file with "func" set to the name of the syscall. */ + +#include "syscallasm.h" + +#define concat(a,b) a##b +#define makesys(a) concat (SYS_, a) + + defsyscall (func, makesys(func)) diff --git a/libgloss/sparc/libsys/template_r.S b/libgloss/sparc/libsys/template_r.S new file mode 100644 index 0000000..3a9b5f8 --- /dev/null +++ b/libgloss/sparc/libsys/template_r.S @@ -0,0 +1,26 @@ +/* reentrant system call template */ + +/* Lots of system calls are trivial functions, so we build their source files + from a template. New syscalls can be added simply by editing the + Makefile! + + The system calls aren't necessarily reentrant. If we were being used in + an embedded system they could be. Reentrant syscalls are also used, + however, to provide ANSI C namespace clean access to the host o/s. + + Usage: Compile this file with "func" set to the name of the syscall. */ + +#include "syscallasm.h" + +#define concat(a,b) a##b +#define concat3(a,b,c) a##b##c +#define makesys(a) concat (SYS_, a) +#define make_r_fn(a) concat3 (_, a, _r) + +/* The leading _'s get turned into #'s by the Makefile. */ + +_ifdef REENT + defsyscall_r (make_r_fn (func), makesys (func)) +_else + defsyscall (func, makesys (func)) +_endif diff --git a/libgloss/sparc/salib-701.c b/libgloss/sparc/salib-701.c new file mode 100644 index 0000000..404ad6c --- /dev/null +++ b/libgloss/sparc/salib-701.c @@ -0,0 +1,288 @@ +/* Stand-alone library for Sparclet 701 board + * + * Copyright (c) 1996 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. + */ + +#define RAM_BASE ((unsigned char *)0x12000000) /* Start of cacheable dram */ +#define DCACHE_LINES 128 /* Number of lines in data cache */ +#define DCACHE_LINE_SIZE 16 /* Bytes per data cache line */ +#define DCACHE_BANKS 4 /* 4-way associative */ +#define CACHE_INST_TAG_ADDR ((unsigned char *)0xc0020000) /* I-Cache tag base address */ +#define ALL_BANKS 0x0000f000 /* Selects all 4 cache banks */ +#define ICACHE_LINES 128 /* Number of lines in inst cache */ +#define ICACHE_LINE_SIZE 32 /* Bytes per inst cache line */ + +/* I/O Base addresses */ +#define CACHE_INST_BASE_ADD 0xc0000000 +#define CACHE_DATA_BASE_ADD 0xc8000000 +#define _InstrCacheCtlBase 0xc0000000 +#define _DataCacheCtlBase 0xc8000000 + +#define USART_BASE_ADD 0x92000000 +#define USART_BASE_ADRS(n) (USART_BASE_ADD + ((n)<<21)) /*0..3*/ + +/* Serial receiver definitions */ +#define USART_RX_CHAR(n) (*(unsigned char *) (USART_BASE_ADRS(n) +(2<<19))) +#define USART_RX_CTRL_BASE_ADRS(n) (USART_BASE_ADRS(n)+(3<<19)) +#define URSTR(n) (*(unsigned int *) (USART_RX_CTRL_BASE_ADRS(n)+(2<<15))) +#define URSTR_CHAR_NUM 0x1f00 /* Bits 8-12 */ + +/* Serial receiver definitions */ +#define USART_TX_CHAR(n) (*(unsigned char *) (USART_BASE_ADRS(n)+3)) +#define USART_TX_CTRL_BASE_ADRS(n) (USART_BASE_ADRS(n)+(1<<19)) +#define UTSTR(n) (*(unsigned int *) (USART_TX_CTRL_BASE_ADRS(n)+(2<<15))) +#define UTSTR_CHAR_FREE 0x1f0 /* Bits 4-8 */ + +/* Cache definitions */ +#define DCCA_NB_LINES 128 /* Nb of lines of the cache */ +/* Bank number, used for Cache Memory and Cache Tag */ +#define ICCA_B3 0x000008000 /* Bit 15 - 1:Bank3 selected */ +#define ICCA_B2 0x000004000 /* Bit 14 - 1:Bank2 selected */ +#define ICCA_B1 0x000002000 /* Bit 13 - 1:Bank1 selected */ +#define ICCA_B0 0x000001000 /* Bit 12 - 1:Bank0 selected */ +/* Register address, show which register is to be checked/updated */ +#define ICCACR 0x00000000 /* Bits 17 - 16 - Control register */ +#define ICCAMEM 0x00010000 /* Bits 17 - 16 - Cache memory */ +#define DCCACR 0x00000000 /* Bits 16 - 15 - Control register */ +/* Instruction Cache Controller Register */ +#define ICCR_DISABLE 0xfffffffe /* Reset enable bit */ + +/* Serial I/O routines */ + +#define STUB_PORT 1 /* 0 = serial port A; 1 = serial port B */ + +static volatile unsigned char *rx_fifo = &USART_RX_CHAR(STUB_PORT); +static volatile unsigned int *rx_status = &URSTR(STUB_PORT); + +static volatile unsigned char *tx_fifo = &USART_TX_CHAR(STUB_PORT); +static volatile unsigned int *tx_status = &UTSTR(STUB_PORT); + +/* library-free debug reoutines */ +#ifdef XDEBUG +#define XDBG_MSG(x) pmsg(x) +#define XDBG_HEX(x) phex(x) +#else +#define XDBG_MSG(x) +#define XDBG_HEX(x) +#endif + +static int +rx_rdy() +{ + return (*rx_status & URSTR_CHAR_NUM); +} + +static unsigned char +rx_char() +{ + return *rx_fifo; +} + +void +tx_char(char c) +{ + *tx_fifo = c; +} + +static int +tx_rdy() +{ + return (*tx_status & UTSTR_CHAR_FREE); +} + +int +getDebugChar() +{ + while (!rx_rdy()) + ; + return rx_char(); +} + +void +putDebugChar(int c) +{ + while (!tx_rdy()) + ; + tx_char(c); +} + +#ifdef XDEBUG +/* library-free debug reoutines */ +/* print a string */ +void pmsg(char *p) +{ + while (*p) + { + if (*p == '\n') + putDebugChar('\r'); + putDebugChar(*p++); + } +} + +/* print a hex number */ +void phex(long x) +{ + char buf[9]; + int i; + + buf[8] = '\0'; + for (i = 7; i >= 0; i--) + { + char c = x & 0x0f; + buf[i] = c < 10 ? c + '0' : c - 10 + 'A'; + x >>= 4; + } + pmsg(buf); +} +#endif + +/* rdtbr() - read the trap base register */ + +unsigned long rdtbr(); + +asm(" + .text + .align 4 + .globl _rdtbr +_rdtbr: + retl + mov %tbr, %o0 +"); + +/* wrtbr() - write the trap base register */ + +void wrtbr(unsigned long); + +asm(" + .text + .align 4 + .globl _wrtbr +_wrtbr: + retl + mov %o0, %tbr +"); + +/* Each entry in the trap vector occupies four words. */ + +struct trap_entry +{ + unsigned sethi_filler:10; + unsigned sethi_imm22:22; + unsigned jmpl_filler:19; + unsigned jmpl_simm13:13; + unsigned long filler[2]; +}; + +extern struct trap_entry fltr_proto; +asm (" + .data + .globl _fltr_proto + .align 4 +_fltr_proto: ! First level trap routine prototype + sethi 0, %l0 + jmpl 0+%l0, %g0 + nop + nop + + .text + .align 4 +"); + +/* copy_vectors - Copy the trap vectors from ROM to RAM, set the TBR register + to point to the RAM vectors, and return the address of the RAM vectors. */ + +extern struct trap_entry __trap_vectors[256]; /* defined in matra.ld */ + +struct trap_entry *copy_vectors() +{ + int i; + struct trap_entry *old = (struct trap_entry *) (rdtbr() & ~0xfff); + + XDBG_MSG("Copying vectors...\n"); + for (i = 0; i < 256; i++) + __trap_vectors[i] = old[i]; + wrtbr ((unsigned long)__trap_vectors); + XDBG_MSG("Done\n"); + return __trap_vectors; +} + + +void +disable_cache() +{ + unsigned long *ptr; + static unsigned long CACHE_shadow_iccr = 0; /* Because CR cannot be read */ + static unsigned long CACHE_shadow_dccr = 0; /* Because CR cannot be read */ + + XDBG_MSG("Disabling cache...\n"); + ptr = (unsigned long*)(CACHE_INST_BASE_ADD | ICCACR); + CACHE_shadow_iccr = CACHE_shadow_iccr & ICCR_DISABLE; + *ptr = CACHE_shadow_iccr; + + ptr = (unsigned long*)(CACHE_DATA_BASE_ADD | DCCACR); + CACHE_shadow_dccr = CACHE_shadow_dccr & ICCR_DISABLE; + *ptr = CACHE_shadow_dccr; + XDBG_MSG("Done\n"); +} + +/* Flush the instruction cache. We need to do this for the debugger stub so + that breakpoints, et. al. become visible to the instruction stream after + storing them in memory. FIXME!! + */ + +void +flush_i_cache () +{ + volatile unsigned char *addr; + + /* First, force all dirty items in the data cache to be moved out to real + memory. This is done by making read refs to alternate addresses that will + fill up all four banks for each line. Note that we actually have to + reference 8 locs per line just in case the region of memory we use is one + of the areas that needs to be flushed. */ + + for (addr = RAM_BASE; + addr < RAM_BASE + (DCACHE_LINES * DCACHE_LINE_SIZE * DCACHE_BANKS) * 2; + addr += DCACHE_LINE_SIZE) + *addr; /* Read the loc */ + + /* Now, flush the instruction cache. */ + + for (addr = CACHE_INST_TAG_ADDR + ALL_BANKS; + addr <= CACHE_INST_TAG_ADDR + ALL_BANKS + ICACHE_LINES * ICACHE_LINE_SIZE; + addr += ICACHE_LINE_SIZE) + *(unsigned long *)addr = 0; /* Clr tag entry for all banks on this line */ +} + +/* Setup trap TT to go to ROUTINE. */ + +void +exceptionHandler (int tt, unsigned long routine) +{ + static struct trap_entry *tb; /* Trap vector base address */ + + if (!tb) + { + tb = copy_vectors(); /* Copy trap vectors to RAM */ + disable_cache(); /* Disable cache FIXME!! */ + } + + XDBG_MSG("Setting exception handler for trap...\n"); + + tb[tt] = fltr_proto; + + tb[tt].sethi_imm22 = routine >> 10; + tb[tt].jmpl_simm13 = routine & 0x3ff; + + XDBG_MSG("Done\n"); +} diff --git a/libgloss/sparc/salib.c b/libgloss/sparc/salib.c new file mode 100644 index 0000000..8076a6b --- /dev/null +++ b/libgloss/sparc/salib.c @@ -0,0 +1,388 @@ +/* Stand-alone library for SPARClite + * + * Copyright (c) 1995 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. + */ + +#include "sparclite.h" +#include "asm.h" + +/* LED blinking pattern can be changed by modifying __led_algorithm. */ + +enum ledtype +{ + led_marching, /* marching pattern, only one led on at a time */ + led_random, /* pseudo-random pattern */ + led_blinking, /* all leds blink on and off */ + led_none /* leds off all the time */ +}; + +enum ledtype __led_algorithm = led_marching; + + +/* Pointer to hook for outbyte, set by stub's exception handler. */ +void (*__outbyte_hook) (int c); + +#ifdef SL931 +#define SDTR_BASE 0x200 +#define SDTR_ASI 1 +#define SDTR_SHIFT 0 +#else +#define SDTR_BASE 0x10000000 +#define SDTR_ASI 4 +#define SDTR_SHIFT 16 +#endif + +#define get_uart_status(PORT) \ + (read_asi (SDTR_ASI, SDTR_BASE + 0x24 + (PORT) * 0x10) >> SDTR_SHIFT) + +#define xmt_char(PORT, C) \ + write_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10, (C) << SDTR_SHIFT) + +#define rcv_char(PORT) \ + (read_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10) >> SDTR_SHIFT) + +void putDebugChar(); + +#if 0 +void +set_uart (cmd) + int cmd; +{ + write_asi (SDTR_ASI, SDTR_BASE + 0x24, cmd << SDTR_SHIFT); +} + +void +set_timer_3 (val) + int val; +{ + write_asi (SDTR_ASI, SDTR_BASE + 0x78, val << SDTR_SHIFT); +} +#endif + + +asm(" + .text + .align 4 + +! Register window overflow handler. Come here when save would move us +! into the invalid window. This routine runs with traps disabled, and +! must be careful not to touch the condition codes, as PSR is never +! restored. +! +! We are called with %l0 = wim, %l1 = pc, %l2 = npc + + .globl " STRINGSYM(win_ovf) " +" STRINGSYM(win_ovf) ": + mov %g1, %l3 ! Save g1, we use it to hold the wim + srl %l0, 1, %g1 ! Rotate wim right + sll %l0, __WINSIZE-1, %l0 + or %l0, %g1, %g1 + + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l3, %g1 ! Restore %g1 + + jmpl %l1, %g0 + rett %l2 + +! Register window underflow handler. Come here when restore would move us +! into the invalid window. This routine runs with traps disabled, and +! must be careful not to touch the condition codes, as PSR is never +! restored. +! +! We are called with %l0 = wim, %l1 = pc, %l2 = npc + + .globl " STRINGSYM(win_unf) " +" STRINGSYM(win_unf) ": + sll %l0, 1, %l3 ! Rotate wim left + srl %l0, __WINSIZE-1, %l0 + or %l0, %l3, %l0 + + mov %l0, %wim ! Install the new wim + + restore ! User's window + restore ! His caller's window + + ldd [%sp + 0 * 4], %l0 ! restore L & I registers + ldd [%sp + 2 * 4], %l2 + ldd [%sp + 4 * 4], %l4 + ldd [%sp + 6 * 4], %l6 + + ldd [%sp + 8 * 4], %i0 + ldd [%sp + 10 * 4], %i2 + ldd [%sp + 12 * 4], %i4 + ldd [%sp + 14 * 4], %i6 + + save %g0, %g0, %g0 ! Back to trap window + save %g0, %g0, %g0 + + jmpl %l1, %g0 + rett %l2 + +! Read the TBR. + + .globl " STRINGSYM(rdtbr) " +" STRINGSYM(rdtbr) ": + retl + mov %tbr, %o0 + +"); + +extern unsigned long rdtbr(); + +void +die(val) + int val; +{ + static unsigned char *leds = (unsigned char *)0x02000003; + + *leds = val; + + while (1) ; +} + +/* Each entry in the trap vector occupies four words. */ + +struct trap_entry +{ + unsigned sethi_filler:10; + unsigned sethi_imm22:22; + unsigned jmpl_filler:19; + unsigned jmpl_simm13:13; + unsigned long filler[2]; +}; + +extern struct trap_entry fltr_proto; +asm (" + .data + .globl " STRINGSYM(fltr_proto) " + .align 4 +" STRINGSYM(fltr_proto) ": ! First level trap routine prototype + sethi 0, %l0 + jmpl 0+%l0, %g0 + nop + nop + + .text + .align 4 +"); + +/* Setup trap TT to go to ROUTINE. If TT is between 0 and 255 inclusive, the + normal trap vector will be used. If TT is 256, then it's for the SPARClite + DSU, and that always vectors off to 255 unrelocated. +*/ + +void +exceptionHandler (tt, routine) + int tt; + unsigned long routine; +{ + struct trap_entry *tb; /* Trap vector base address */ + + if (tt != 256) + tb = (struct trap_entry *) (rdtbr() & ~0xfff); + else + { + tt = 255; + tb = (struct trap_entry *) 0; + } + + tb[tt] = fltr_proto; + + tb[tt].sethi_imm22 = routine >> 10; + tb[tt].jmpl_simm13 = routine & 0x3ff; +} + +void +update_leds() +{ + static unsigned char *leds = (unsigned char *)0x02000003; + static enum ledtype prev_algorithm = led_none; + + if (prev_algorithm != __led_algorithm) + { + *leds = 0xff; /* turn the LEDs off */ + prev_algorithm = __led_algorithm; + } + + switch (__led_algorithm) + { + case led_marching: + { + static unsigned char curled = 1; + static unsigned char dir = 0; + + *leds = ~curled; + + if (dir) + curled <<= 1; + else + curled >>= 1; + + if (curled == 0) + { + if (dir) + curled = 0x80; + else + curled = 1; + dir = ~dir; + } + break; + } + + case led_random: + { + static unsigned int next = 0; + *leds = next & 0xff; + next = (next * 1103515245 + 12345) & 0x7fff; + break; + } + + case led_blinking: + { + static unsigned char next = 0; + *leds = next; + next = ~next; + break; + } + + default: + break; + } +} + + /* 1/5th of a second? */ + +#define LEDTIME (20000000 / 500) + +unsigned long ledtime = LEDTIME; + +int +inbyte() +{ + return (getDebugChar()); +} + +int +getDebugChar() +{ + unsigned long countdown = ledtime; + + update_leds(); + + while (1) + { + if ((get_uart_status(0) & 2) != 0) break; + + if (countdown-- == 0) + { + countdown = ledtime; + update_leds(); + } + } + + return rcv_char(0); +} + +/* Output one character to the serial port */ +void +outbyte(c) + int c; +{ + if (__outbyte_hook) + __outbyte_hook (c); + else + putDebugChar(c); +} + +void +putDebugChar(c) + int c; +{ + update_leds(); + + while ((get_uart_status(0) & 1) == 0) ; + + xmt_char(0, c); +} + +#if 0 +int +write(fd, data, length) + int fd; + unsigned char *data; + int length; +{ + int olength = length; + + while (length--) + putDebugChar(*data++); + + return olength; +} + +int +read(fd, data, length) + int fd; + unsigned char *data; + int length; +{ + int olength = length; + int c; + + while (length--) + *data++ = getDebugChar(); + + return olength; +} +#endif + +/* Set the baud rate for the serial port, returns 0 for success, + -1 otherwise */ + +#if 0 +int +set_baud_rate(baudrate) + int baudrate; +{ + /* Convert baud rate to uart clock divider */ + switch (baudrate) + { + case 38400: + baudrate = 16; + break; + case 19200: + baudrate = 33; + break; + case 9600: + baudrate = 65; + break; + default: + return -1; + } + + set_timer_3(baudrate); /* Set it */ +} +#endif diff --git a/libgloss/sparc/slite.h b/libgloss/sparc/slite.h new file mode 100644 index 0000000..4762e3f --- /dev/null +++ b/libgloss/sparc/slite.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1995, 1996 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. + */ + +#define STACK_SIZE 16 * 1024 +#define TRAP_STACK_SIZE 4 * 1024 +#define NUM_REGS 20 + +#ifdef SL933 +#define NUMBER_OF_REGISTER_WINDOWS 6 +#else +#define NUMBER_OF_REGISTER_WINDOWS 8 +#endif + +#if (NUMBER_OF_REGISTER_WINDOWS == 8) +#define SPARC_PSR_CWP_MASK 0x07 /* bits 0 - 4 */ +#elif (NUMBER_OF_REGISTER_WINDOWS == 16) +#define SPARC_PSR_CWP_MASK 0x0F /* bits 0 - 4 */ +#elif (NUMBER_OF_REGISTER_WINDOWS == 32) +#define SPARC_PSR_CWP_MASK 0x1F /* bits 0 - 4 */ +#else +#error "Unsupported number of register windows for this cpu" +#endif + +/* The traptable has to be the first code in a boot PROM. */ + +/* + * Entry for traps which jump to a programmer-specified trap handler. + */ + +#define TRAP(_handler) \ + sethi %hi(_handler), %l3 ; \ + jmpl %l3+%lo(_handler), %g0 ; \ + mov %wim, %l0 ; \ + nop + +/* Unexcpected trap will halt the processor by forcing it to error state */ +#if 1 +#define BAD_TRAP ta 0; nop; nop; nop; +#else +#define BAD_TRAP \ + mov %psr, l0 ; \ + mov 0x0, %o0 ; \ + sethi %hi(SYM(bad_trap)), l4 ; \ + jmp l4+%lo(SYM(bad_trap)); +#endif + +/* Software trap. Treat as BAD_TRAP for the time being... */ +#if 1 +#define SOFT_TRAP BAD_TRAP +#else +#define SOFT_TRAP \ + mov $psr, $l0 ; \ + mov 0x0, $o0 ; \ + sethi $hi(SYM(soft_trap)), l4 ; \ + jmp l4+$lo(SYM(soft_trap)); +#endif + +#define PSR_INIT 0x10c0 /* Disable traps, set s and ps */ +#define TBR_INIT 0 +#define WIM_INIT 2 +#define SP_INIT 0x023ffff0 + +/* Macros for reading and writing to arbitrary address spaces. Note that ASI + must be a constant (sorry, but the SPARC can only specify ASIs as part of an + instruction. */ + +#define read_asi(ASI, LOC) \ + ({ \ + unsigned int val; \ + __asm__ volatile ("lda [%r1]%2,%0" : "=r" (val) : "rJ" (LOC), "I" (ASI)); \ + val; \ + }) + +#define write_asi(ASI, LOC, VAL) \ + __asm__ volatile ("sta %0,[%r1]%2" : : "r" (VAL), "rJ" (LOC), "I" (ASI)); + +/* + * Use this when modifying registers that cause memory to be modified. This + * will cause GCC to reload all values after this point. + */ +#define write_asi_volatile(ASI, LOC, VAL) \ + __asm__ volatile ("sta %0,[%r1]%2" : : "r" (VAL), "rJ" (LOC), "I" (ASI) \ + : "memory"); + +#define WRITE_PC(x) registers[PC] = x; registers[NPC] = x + 4; + +/* + * Processor Status Register (psr) + * + * 31 28|27 24|23 20|19 12|11 9|7|6|5|4 0 + * +------+-------+-------+-------+------+-+-+-+--------+ + * | impl | ver | icc | res. | pil | | | | cwp | + * +------+-------+-------+-------+------+-+-+-+--------+ + * S P E + * S T + * if ET = 1, traps are enabled, 0 means disabled. + * if S = 1, you're in supervisor mode, 0 means user mode. + * cwp points to the current window. + * + * Trap Base Register (tbr) + * + * 31 12|11 4|3 0 + * +--------------+--------------+------+ + * | tba | tt | null | + * +--------------+--------------+------+ + * + * tba contains the most sig. 20 bits of the tbr base address + * tt is the trap number. + * + * Window Invalid Register (wim) + * 31 8| 7| 6| 5| 4| 3| 2| 1| 0 + * +-------------+--+--+--+--+--+--+--+--+ + * | res. |w7|w6|w5|w4|w3|w2|w1|w0| + * +-------------+--+--+--+--+--+--+--+--+ + */ + diff --git a/libgloss/sparc/sparc-stub.c b/libgloss/sparc/sparc-stub.c new file mode 100644 index 0000000..fa21d72 --- /dev/null +++ b/libgloss/sparc/sparc-stub.c @@ -0,0 +1,848 @@ +#include "sparclite.h" +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * + * This code has been extensively tested on the Fujitsu SPARClite demo board. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include <string.h> +#include <signal.h> + +/************************************************************************ + * + * external low-level support routines + */ + +extern putDebugChar(); /* write a single character */ +extern getDebugChar(); /* read and return a single char */ + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 2048 + +static int initialized = 0; /* !0 means we've been initialized */ + +static void set_mem_fault_trap(); + +static const char hexchars[]="0123456789abcdef"; + +#define NUMREGS 72 + +/* Number of bytes of registers. */ +#define NUMREGBYTES (NUMREGS * 4) +enum regnames {G0, G1, G2, G3, G4, G5, G6, G7, + O0, O1, O2, O3, O4, O5, SP, O7, + L0, L1, L2, L3, L4, L5, L6, L7, + I0, I1, I2, I3, I4, I5, FP, I7, + + F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR }; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +extern void trap_low(); + +asm(" + .reserve trapstack, 1000 * 4, \"bss\", 8 + + .data + .align 4 + +in_trap_handler: + .word 0 + + .text + .align 4 + +! This function is called when any SPARC trap (except window overflow or +! underflow) occurs. It makes sure that the invalid register window is still +! available before jumping into C code. It will also restore the world if you +! return from handle_exception. + + .globl _trap_low +_trap_low: + mov %psr, %l0 + mov %wim, %l3 + + srl %l3, %l0, %l4 ! wim >> cwp + cmp %l4, 1 + bne window_fine ! Branch if not in the invalid window + nop + +! Handle window overflow + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + tst %g1 + bg good_wim ! Branch if new wim is non-zero + nop + +! At this point, we need to bring a 1 into the high order bit of the wim. +! Since we don't want to make any assumptions about the number of register +! windows, we figure it out dynamically so as to setup the wim correctly. + + not %g1 ! Fill g1 with ones + mov %g1, %wim ! Fill the wim with ones + nop + nop + nop + mov %wim, %g1 ! Read back the wim + inc %g1 ! Now g1 has 1 just to left of wim + srl %g1, 1, %g1 ! Now put 1 at top of wim + mov %g0, %wim ! Clear wim so that subsequent save + nop ! won't trap + nop + nop + +good_wim: + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l4, %g1 ! Restore %g1 + +window_fine: + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 + + set trapstack+1000*4, %sp ! Switch to trap stack + +recursive_trap: + st %l5, [%lo(in_trap_handler) + %l4] + sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals + ! + hidden arg + arg spill + ! + doubleword alignment + ! + registers[72] local var + + std %g0, [%sp + (24 + 0) * 4] ! registers[Gx] + std %g2, [%sp + (24 + 2) * 4] + std %g4, [%sp + (24 + 4) * 4] + std %g6, [%sp + (24 + 6) * 4] + + std %i0, [%sp + (24 + 8) * 4] ! registers[Ox] + std %i2, [%sp + (24 + 10) * 4] + std %i4, [%sp + (24 + 12) * 4] + std %i6, [%sp + (24 + 14) * 4] + ! F0->F31 not implemented + mov %y, %l4 + mov %tbr, %l5 + st %l4, [%sp + (24 + 64) * 4] ! Y + st %l0, [%sp + (24 + 65) * 4] ! PSR + st %l3, [%sp + (24 + 66) * 4] ! WIM + st %l5, [%sp + (24 + 67) * 4] ! TBR + st %l1, [%sp + (24 + 68) * 4] ! PC + st %l2, [%sp + (24 + 69) * 4] ! NPC + + ! CPSR and FPSR not impl + + or %l0, 0xf20, %l4 + mov %l4, %psr ! Turn on traps, disable interrupts + + call _handle_exception + add %sp, 24 * 4, %o0 ! Pass address of registers + +! Reload all of the registers that aren't on the stack + + ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx] + ldd [%sp + (24 + 2) * 4], %g2 + ldd [%sp + (24 + 4) * 4], %g4 + ldd [%sp + (24 + 6) * 4], %g6 + + ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox] + ldd [%sp + (24 + 10) * 4], %i2 + ldd [%sp + (24 + 12) * 4], %i4 + ldd [%sp + (24 + 14) * 4], %i6 + + ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR + ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC + + restore ! Ensure that previous window is valid + save %g0, %g0, %g0 ! by causing a window_underflow trap + + mov %l0, %y + mov %l1, %psr ! Make sure that traps are disabled + ! for rett + + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + dec %l5 + st %l5, [%lo(in_trap_handler) + %l4] + + jmpl %l2, %g0 ! Restore old PC + rett %l3 ! Restore old nPC +"); + +/* Convert ch from a hex digit to an int */ + +static int +hex(ch) + unsigned char ch; +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +/* scan for the sequence $<data>#<checksum> */ + +static void +getpacket(buffer) + char *buffer; +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do + { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) + { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + + if (count >= BUFMAX) + continue; + + buffer[count] = 0; + + if (ch == '#') + { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum |= hex(getDebugChar() & 0x7f); +#if 0 + /* Humans shouldn't have to figure out checksums to type to it. */ + putDebugChar ('+'); + return; +#endif + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else + { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i=3; i <= count; i++) + buffer[i-3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + +/* send the packet in buffer. */ + +static void +putpacket(buffer) + unsigned char *buffer; +{ + unsigned char checksum; + int count; + unsigned char ch; + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar('$'); + checksum = 0; + count = 0; + + while (ch = buffer[count]) + { + if (! putDebugChar(ch)) + return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum & 0xf]); + + } + while ((getDebugChar() & 0x7f) != '+'); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +static volatile int mem_err = 0; + +/* Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ + +static unsigned char * +mem2hex(mem, buf, count, may_fault) + unsigned char *mem; + unsigned char *buf; + int count; + int may_fault; +{ + unsigned char ch; + + set_mem_fault_trap(may_fault); + + while (count-- > 0) + { + ch = *mem++; + if (mem_err) + return 0; + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + + set_mem_fault_trap(0); + + return buf; +} + +/* convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written */ + +static char * +hex2mem(buf, mem, count, may_fault) + unsigned char *buf; + unsigned char *mem; + int count; + int may_fault; +{ + int i; + unsigned char ch; + + set_mem_fault_trap(may_fault); + + for (i=0; i<count; i++) + { + ch = hex(*buf++) << 4; + ch |= hex(*buf++); + *mem++ = ch; + if (mem_err) + return 0; + } + + set_mem_fault_trap(0); + + return mem; +} + +/* This table contains the mapping between SPARC hardware trap types, and + signals, which are primarily what GDB understands. It also indicates + which hardware traps we need to commandeer when initializing the stub. */ + +static struct hard_trap_info +{ + unsigned char tt; /* Trap type code for SPARClite */ + unsigned char signo; /* Signal that we map this trap into */ +} hard_trap_info[] = { + {1, SIGSEGV}, /* instruction access error */ + {2, SIGILL}, /* privileged instruction */ + {3, SIGILL}, /* illegal instruction */ + {4, SIGEMT}, /* fp disabled */ + {36, SIGEMT}, /* cp disabled */ + {7, SIGBUS}, /* mem address not aligned */ + {9, SIGSEGV}, /* data access exception */ + {10, SIGEMT}, /* tag overflow */ + {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */ + {0, 0} /* Must be last */ +}; + +/* Set up exception handlers for tracing and breakpoints */ + +void +set_debug_traps() +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + exceptionHandler(ht->tt, trap_low); + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. */ + + putDebugChar ('+'); + + initialized = 1; +} + +asm (" +! Trap handler for memory errors. This just sets mem_err to be non-zero. It +! assumes that %l1 is non-zero. This should be safe, as it is doubtful that +! 0 would ever contain code that could mem fault. This routine will skip +! past the faulting instruction after setting mem_err. + + .text + .align 4 + +_fltr_set_mem_err: + sethi %hi(_mem_err), %l0 + st %l1, [%l0 + %lo(_mem_err)] + jmpl %l2, %g0 + rett %l2+4 +"); + +static void +set_mem_fault_trap(enable) + int enable; +{ + extern void fltr_set_mem_err(); + mem_err = 0; + + if (enable) + exceptionHandler(9, fltr_set_mem_err); + else + exceptionHandler(9, trap_low); +} + +/* Convert the SPARC hardware trap type code to a unix signal number. */ + +static int +computeSignal(tt) + int tt; +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + if (ht->tt == tt) + return ht->signo; + + return SIGHUP; /* default for things we don't know about */ +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +static unsigned int +hexToInt(char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex(**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + +/* + * This function does all command procesing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ + +extern void breakinst(); + +static void +handle_exception (registers) + unsigned long *registers; +{ + int tt; /* Trap type */ + int sigval; + unsigned int addr; + int length; + char *ptr; + unsigned long *sp; + +/* First, we must force all of the windows to be spilled out */ + + asm(" save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + restore + restore + restore + restore + restore + restore + restore + restore +"); + + if (registers[PC] == (unsigned long)breakinst) + { + registers[PC] = registers[NPC]; + registers[NPC] += 4; + } + + sp = (unsigned long *)registers[SP]; + + tt = (registers[TBR] >> 4) & 0xff; + + /* reply to host that an exception has occurred */ + sigval = computeSignal(tt); + ptr = remcomOutBuffer; + + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + *ptr++ = hexchars[PC >> 4]; + *ptr++ = hexchars[PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[FP >> 4]; + *ptr++ = hexchars[FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = hexchars[SP >> 4]; + *ptr++ = hexchars[SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&sp, ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[NPC >> 4]; + *ptr++ = hexchars[NPC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[O7 >> 4]; + *ptr++ = hexchars[O7 & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[O7], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = 0; + + putpacket(remcomOutBuffer); + + while (1) + { + remcomOutBuffer[0] = 0; + + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) + { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval & 0xf]; + remcomOutBuffer[3] = 0; + break; + + case 'd': + /* toggle debug flag */ + break; + + case 'g': /* return the value of the CPU registers */ + { + ptr = remcomOutBuffer; + ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ + ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */ + memset(ptr, '0', 32 * 8); /* Floating point */ + mem2hex((char *)®isters[Y], + ptr + 32 * 4 * 2, + 8 * 4, + 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + } + break; + + case 'G': /* set the value of the CPU registers - return OK */ + { + unsigned long *newsp, psr; + + psr = registers[PSR]; + + ptr = &remcomInBuffer[1]; + hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ + hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */ + hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], + 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + + /* See if the stack pointer has moved. If so, then copy the saved + locals and ins to the new location. This keeps the window + overflow and underflow routines happy. */ + + newsp = (unsigned long *)registers[SP]; + if (sp != newsp) + sp = memcpy(newsp, sp, 16 * 4); + + /* Don't allow CWP to be modified. */ + + if (psr != registers[PSR]) + registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f); + + strcpy(remcomOutBuffer,"OK"); + } + break; + + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length)) + { + if (mem2hex((char *)addr, remcomOutBuffer, length, 1)) + break; + + strcpy (remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer,"E01"); + break; + + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* Try to read '%x,%x:'. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length) + && *ptr++ == ':') + { + if (hex2mem(ptr, (char *)addr, length, 1)) + strcpy(remcomOutBuffer, "OK"); + else + strcpy(remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer, "E02"); + break; + + case 'c': /* cAA..AA Continue at address AA..AA(optional) */ + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr)) + { + registers[PC] = addr; + registers[NPC] = addr + 4; + } + +/* Need to flush the instruction cache here, as we may have deposited a + breakpoint, and the icache probably has no way of knowing that a data ref to + some location may have changed something that is in the instruction cache. + */ + + flush_i_cache(); + return; + + /* kill the program */ + case 'k' : /* do nothing */ + break; +#if 0 + case 't': /* Test feature */ + asm (" std %f30,[%sp]"); + break; +#endif + case 'r': /* Reset */ + asm ("call 0 + nop "); + break; + +#if 0 +Disabled until we can unscrew this properly + + case 'b': /* bBB... Set baud rate to BB... */ + { + int baudrate; + extern void set_timer_3(); + + ptr = &remcomInBuffer[1]; + if (!hexToInt(&ptr, &baudrate)) + { + strcpy(remcomOutBuffer,"B01"); + break; + } + + /* Convert baud rate to uart clock divider */ + switch (baudrate) + { + case 38400: + baudrate = 16; + break; + case 19200: + baudrate = 33; + break; + case 9600: + baudrate = 65; + break; + default: + strcpy(remcomOutBuffer,"B02"); + goto x1; + } + + putpacket("OK"); /* Ack before changing speed */ + set_timer_3(baudrate); /* Set it */ + } +x1: break; +#endif + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void +breakpoint() +{ + if (!initialized) + return; + + asm(" .globl _breakinst + + _breakinst: ta 1 + "); +} diff --git a/libgloss/sparc/sparc86x.ld b/libgloss/sparc/sparc86x.ld new file mode 100644 index 0000000..e7cf27e --- /dev/null +++ b/libgloss/sparc/sparc86x.ld @@ -0,0 +1,177 @@ +/* + *uncomment this if you want the linker to output srecords. +OUTPUT_FORMAT(srec) + * + */ +ENTRY(_start) +STARTUP(crt0.o) +OUTPUT_ARCH(sparc) +SEARCH_DIR(.) +__DYNAMIC = 0; +GROUP (-lc -lslite86x -lgcc) + +/* + * The memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | _stext | + * | _etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _end_text | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + +_STACK_SIZE = (16 * 1024); +_RAM_SIZE = 2M; +_RAM_START = 0x40010000; +_RAM_END = _RAM_START + _RAM_SIZE; + +/* + * Base address of the on-CPU peripherals. This is for compatability + * with the simulator. + */ + +_ERC32_MEC = 0x0; + +/* + * Setup the memory map of the MB86931-EB Board (ex931) + * stack grows down towards low memory. + */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x40010000, LENGTH = 2M +} + +__stack = _RAM_START + _RAM_SIZE - 4 * 16; +__trap_stack = (_RAM_START + _RAM_SIZE - 4 * 16) - _STACK_SIZE; + +/* + * All the symbols that might be accessed from C code need to be + * listed twice, once with an additional underscore. aout format needs + * and extra underscore, whereas coff & elf doesn't. This is to work + * with both. + */ +/* + * Initalize some symbols to be zero so we can reference them in the + * crt0 without core dumping. These functions are all optional, but + * we do this so we can have our crt0 always use them if they exist. + * This is so BSPs work better when using the crt0 installed with gcc. + * We have to initalize them twice, so we cover a.out (which prepends + * an underscore) and coff object file formats. + */ +PROVIDE (hardware_init_hook = 0); +PROVIDE (_hardware_init_hook = 0); +PROVIDE (software_init_hook = 0); +PROVIDE (_software_init_hook = 0); +SECTIONS +{ + .text : { + stext = .; + _stext = .; + __EH_FRAME_BEGIN__ = .; + + CREATE_OBJECT_SYMBOLS + *(.text) + + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + LONG(0) + __DTOR_END__ = .; + + _etext = .; + + *(.init) + *(.lit) + *(.rodata) + *(.shdata) + *(.eh_frame) + *(.gnu.linkonce.t*) + *(.gnu.linkonce.r*) + *(.gcc_except_table) + *(.fini) + + } > ram + .shbss SIZEOF(.text) + ADDR(.text) : { + *(.shbss) + } + .talias : { } > ram + .data ALIGN(0x2000) : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + .bss SIZEOF(.data) + ADDR(.data) : { + sbss = . ; + _sbss = . ; + __bss_start = ALIGN(0x8); + __bss_start = ALIGN(0x8); + *(.bss) + *(COMMON) + end = ALIGN(0x8); + _end = ALIGN(0x8); + __end = ALIGN(0x8); + ebss = .; + _ebss = .; + } + .mstack : { } > ram + .rstack : { } > ram + .stab 0 (NOLOAD) : { + [ .stab ] + } + .stabstr 0 (NOLOAD) : + { + [ .stabstr ] + } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/libgloss/sparc/sparcl-stub.c b/libgloss/sparc/sparcl-stub.c new file mode 100644 index 0000000..634878b --- /dev/null +++ b/libgloss/sparc/sparcl-stub.c @@ -0,0 +1,1005 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware + * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support. + * + * This code has been extensively tested on the Fujitsu SPARClite demo board. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include <string.h> +#include <signal.h> +#include "asm.h" + +/************************************************************************ + * + * external low-level support routines + */ +extern putDebugChar(); /* write a single character */ +extern getDebugChar(); /* read and return a single char */ + +/* Pointer to hook for outbyte, set by stub's exception handler. */ +extern void (*__outbyte_hook)(); + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 2048 + +static int initialized = 0; /* !0 means we've been initialized */ + +extern void breakinst(); +static void hw_breakpoint(); +static void set_mem_fault_trap(); +static void get_in_break_mode(); + +static const char hexchars[]="0123456789abcdef"; + +#define NUMREGS 80 + +/* Number of bytes of registers. */ +#define NUMREGBYTES (NUMREGS * 4) +enum regnames {G0, G1, G2, G3, G4, G5, G6, G7, + O0, O1, O2, O3, O4, O5, SP, O7, + L0, L1, L2, L3, L4, L5, L6, L7, + I0, I1, I2, I3, I4, I5, FP, I7, + + F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR, + DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR }; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +extern void trap_low(); + +asm(" + .reserve trapstack, 1000 * 4, \"bss\", 8 + + .data + .align 4 + +in_trap_handler: + .word 0 + + .text + .align 4 + +! This function is called when any SPARC trap (except window overflow or +! underflow) occurs. It makes sure that the invalid register window is still +! available before jumping into C code. It will also restore the world if you +! return from handle_exception. + + .globl " STRINGSYM(trap_low) " +" STRINGSYM(trap_low) ": + mov %psr, %l0 + mov %wim, %l3 + + srl %l3, %l0, %l4 ! wim >> cwp + cmp %l4, 1 + bne window_fine ! Branch if not in the invalid window + nop + +! Handle window overflow + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + tst %g1 + bg good_wim ! Branch if new wim is non-zero + nop + +! At this point, we need to bring a 1 into the high order bit of the wim. +! Since we don't want to make any assumptions about the number of register +! windows, we figure it out dynamically so as to setup the wim correctly. + + not %g1 ! Fill g1 with ones + mov %g1, %wim ! Fill the wim with ones + nop + nop + nop + mov %wim, %g1 ! Read back the wim + inc %g1 ! Now g1 has 1 just to left of wim + srl %g1, 1, %g1 ! Now put 1 at top of wim + mov %g0, %wim ! Clear wim so that subsequent save + nop ! won't trap + nop + nop + +good_wim: + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l4, %g1 ! Restore %g1 + +window_fine: + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 + + set trapstack+1000*4, %sp ! Switch to trap stack + +recursive_trap: + st %l5, [%lo(in_trap_handler) + %l4] + sub %sp,(16+1+6+1+80)*4,%sp ! Make room for input & locals + ! + hidden arg + arg spill + ! + doubleword alignment + ! + registers[72] local var + + std %g0, [%sp + (24 + 0) * 4] ! registers[Gx] + std %g2, [%sp + (24 + 2) * 4] + std %g4, [%sp + (24 + 4) * 4] + std %g6, [%sp + (24 + 6) * 4] + + std %i0, [%sp + (24 + 8) * 4] ! registers[Ox] + std %i2, [%sp + (24 + 10) * 4] + std %i4, [%sp + (24 + 12) * 4] + std %i6, [%sp + (24 + 14) * 4] + ! F0->F31 not implemented + mov %y, %l4 + mov %tbr, %l5 + st %l4, [%sp + (24 + 64) * 4] ! Y + st %l0, [%sp + (24 + 65) * 4] ! PSR + st %l3, [%sp + (24 + 66) * 4] ! WIM + st %l5, [%sp + (24 + 67) * 4] ! TBR + st %l1, [%sp + (24 + 68) * 4] ! PC + st %l2, [%sp + (24 + 69) * 4] ! NPC + ! CPSR and FPSR not impl + or %l0, 0xf20, %l4 + mov %l4, %psr ! Turn on traps, disable interrupts + nop + nop + nop + call " STRINGSYM(get_in_break_mode) " + nop + nop + nop + + sethi %hi(0xff00), %l5 + or %l5, %lo(0xff00), %l5 + + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 72) * 4] ! DIA1, debug instr addr 1 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 73) * 4] ! DIA2, debug instr addr 2 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 74) * 4] ! DDA1, debug data addr 1 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 75) * 4] ! DDA2, debug data addr 2 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 76) * 4] ! DDV1, debug data val 1 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 77) * 4] ! DDV2, debug data val 2 + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 78) * 4] ! DCR, debug control reg + add %l5, 4, %l5 + lda [%l5]0x1, %l4 + st %l4, [%sp + (24 + 79) * 4] ! DSR, debug status reg + nop + nop + or %l0, 0xf20, %l4 + mov %l4, %psr ! Turn on traps, disable interrupts + nop + nop + nop + call " STRINGSYM(handle_exception) " + add %sp, 24 * 4, %o0 ! Pass address of registers + +! Reload all of the registers that aren't on the stack + + ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx] + ldd [%sp + (24 + 2) * 4], %g2 + ldd [%sp + (24 + 4) * 4], %g4 + ldd [%sp + (24 + 6) * 4], %g6 + + ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox] + ldd [%sp + (24 + 10) * 4], %i2 + ldd [%sp + (24 + 12) * 4], %i4 + ldd [%sp + (24 + 14) * 4], %i6 + + sethi %hi(0xff00), %l2 + or %l2, %lo(0xff00), %l2 + ldd [%sp + (24 + 72) * 4], %l4 ! DIA1, debug instr addr 1 + stda %l4, [%l2]0x1 + nop + nop + nop + nop + ldd [%sp + (24 + 74) * 4], %l4 ! DDA1, debug data addr 1 + add %l2, 8, %l2 + stda %l4, [%l2]0x1 + nop + nop + nop + nop + ldd [%sp + (24 + 76) * 4], %l4 ! DDV1, debug data value 1 + add %l2, 8, %l2 + stda %l4, [%l2]0x1 + nop + nop + nop + nop + ld [%sp + (24 + 78) * 4], %l4 ! DCR, debug control reg + ld [%sp + (24 + 79) * 4], %l5 ! DSR, debug control reg + add %l2, 8, %l2 + or %l4, 0x200, %l4 + sta %l4, [%l2]0x1 + add %l2, 4, %l2 + sta %l5, [%l2]0x1 + nop + nop + nop + nop + + ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR + ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC + + restore ! Ensure that previous window is valid + save %g0, %g0, %g0 ! by causing a window_underflow trap + + mov %l0, %y + mov %l1, %psr ! Make sure that traps are disabled + ! for rett + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + dec %l5 + st %l5, [%lo(in_trap_handler) + %l4] + + jmpl %l2, %g0 ! Restore old PC + rett %l3 ! Restore old nPC +"); + +/* Convert ch from a hex digit to an int */ + +static int +hex(ch) + unsigned char ch; +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +/* scan for the sequence $<data>#<checksum> */ + +static void +getpacket(buffer) + char *buffer; +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do + { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$') ; + + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) + { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + + if (count >= BUFMAX) + continue; + + buffer[count] = 0; + + if (ch == '#') + { + xmitcsum = hex(getDebugChar() & 0x7f) << 4; + xmitcsum |= hex(getDebugChar() & 0x7f); +#if 0 + /* Humans shouldn't have to figure out checksums to type to it. */ + putDebugChar ('+'); + return; +#endif + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else + { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i=3; i <= count; i++) + buffer[i-3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + +/* send the packet in buffer. */ + +static void +putpacket(buffer) + unsigned char *buffer; +{ + unsigned char checksum; + int count; + unsigned char ch; + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar('$'); + checksum = 0; + count = 0; + + while (ch = buffer[count]) + { + if (! putDebugChar(ch)) + return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum & 0xf]); + + } + while ((getDebugChar() & 0x7f) != '+'); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +static volatile int mem_err = 0; + +/* Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ + +static unsigned char * +mem2hex(mem, buf, count, may_fault) + unsigned char *mem; + unsigned char *buf; + int count; + int may_fault; +{ + unsigned char ch; + + set_mem_fault_trap(may_fault); + + while (count-- > 0) + { + ch = *mem++; + if (mem_err) + return 0; + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + + set_mem_fault_trap(0); + + return buf; +} + +/* convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written */ + +static char * +hex2mem(buf, mem, count, may_fault) + unsigned char *buf; + unsigned char *mem; + int count; + int may_fault; +{ + int i; + unsigned char ch; + + set_mem_fault_trap(may_fault); + + for (i=0; i<count; i++) + { + ch = hex(*buf++) << 4; + ch |= hex(*buf++); + *mem++ = ch; + if (mem_err) + return 0; + } + + set_mem_fault_trap(0); + + return mem; +} + +/* This table contains the mapping between SPARC hardware trap types, and + signals, which are primarily what GDB understands. It also indicates + which hardware traps we need to commandeer when initializing the stub. */ + +static struct hard_trap_info +{ + unsigned char tt; /* Trap type code for SPARClite */ + unsigned char signo; /* Signal that we map this trap into */ +} hard_trap_info[] = { + {1, SIGSEGV}, /* instruction access error */ + {2, SIGILL}, /* privileged instruction */ + {3, SIGILL}, /* illegal instruction */ + {4, SIGEMT}, /* fp disabled */ + {36, SIGEMT}, /* cp disabled */ + {7, SIGBUS}, /* mem address not aligned */ + {9, SIGSEGV}, /* data access exception */ + {10, SIGEMT}, /* tag overflow */ + {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */ + {255, SIGTRAP}, /* hardware breakpoint */ + {0, 0} /* Must be last */ +}; + +/* Set up exception handlers for tracing and breakpoints */ + +void +set_debug_traps() +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + exceptionHandler(ht->tt, trap_low); + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. */ + + putDebugChar ('+'); + + initialized = 1; +} + +asm (" +! Trap handler for memory errors. This just sets mem_err to be non-zero. It +! assumes that %l1 is non-zero. This should be safe, as it is doubtful that +! 0 would ever contain code that could mem fault. This routine will skip +! past the faulting instruction after setting mem_err. + + .text + .align 4 + +" STRINGSYM(fltr_set_mem_err) ": + sethi %hi(" STRINGSYM(mem_err) "), %l0 + st %l1, [%l0 + %lo(" STRINGSYM(mem_err) ")] + jmpl %l2, %g0 + rett %l2+4 +"); + +static void +set_mem_fault_trap(enable) + int enable; +{ + extern void fltr_set_mem_err(); + mem_err = 0; + + if (enable) + exceptionHandler(9, fltr_set_mem_err); + else + exceptionHandler(9, trap_low); +} + +asm (" + .text + .align 4 + +" STRINGSYM(dummy_hw_breakpoint) ": + jmpl %l2, %g0 + rett %l2+4 + nop + nop +"); + +static void +set_hw_breakpoint_trap(enable) + int enable; +{ + extern void dummy_hw_breakpoint(); + + if (enable) + exceptionHandler(255, dummy_hw_breakpoint); + else + exceptionHandler(255, trap_low); +} + +static void +get_in_break_mode() +{ + set_hw_breakpoint_trap(1); + + asm(" + sethi %hi(0xff10), %l4 + or %l4, %lo(0xff10), %l4 + sta %g0, [%l4]0x1 + nop + nop + nop + "); + + set_hw_breakpoint_trap(0); +} + +/* Convert the SPARC hardware trap type code to a unix signal number. */ + +static int +computeSignal(tt) + int tt; +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + if (ht->tt == tt) + return ht->signo; + + return SIGHUP; /* default for things we don't know about */ +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +static int +hexToInt(char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex(**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + +/* Replacement for outbyte that sends a packet to GDB containing + the character to be output. */ + +static void +outbyte_stub (int c) +{ + static char buf[4]; + + buf[0] = 'O'; + buf[1] = hexchars[(c >> 4) & 0xf]; + buf[2] = hexchars[c % 16]; + buf[3] = 0; + putpacket (buf); +} + + +/* + * This function does all command procesing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ + + +static void +handle_exception (registers) + unsigned long *registers; +{ + int tt; /* Trap type */ + int sigval; + int addr; + int length; + char *ptr; + unsigned long *sp; + unsigned long dsr; + +/* First, we must force all of the windows to be spilled out */ + + asm(" save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + restore + restore + restore + restore + restore + restore + restore + restore +"); + + if (registers[PC] == (unsigned long)breakinst) + { + registers[PC] = registers[NPC]; + registers[NPC] += 4; + } + sp = (unsigned long *)registers[SP]; + + dsr = (unsigned long)registers[DSR]; + if (dsr & 0x3c) + { + tt = 255; + } + else + { + tt = (registers[TBR] >> 4) & 0xff; + } + + /* reply to host that an exception has occurred */ + sigval = computeSignal(tt); + ptr = remcomOutBuffer; + + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + *ptr++ = hexchars[PC >> 4]; + *ptr++ = hexchars[PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[FP >> 4]; + *ptr++ = hexchars[FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = hexchars[SP >> 4]; + *ptr++ = hexchars[SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&sp, ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[NPC >> 4]; + *ptr++ = hexchars[NPC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[O7 >> 4]; + *ptr++ = hexchars[O7 & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[O7], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = 0; + + putpacket(remcomOutBuffer); + + __outbyte_hook = outbyte_stub; + + while (1) + { + remcomOutBuffer[0] = 0; + + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) + { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval & 0xf]; + remcomOutBuffer[3] = 0; + break; + + case 'd': + /* toggle debug flag */ + break; + + case 'g': /* return the value of the CPU registers */ + { + ptr = remcomOutBuffer; + ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ + ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */ + memset(ptr, '0', 32 * 8); /* Floating point */ + ptr = mem2hex((char *)®isters[Y], + ptr + 32 * 4 * 2, + 8 * 4, + 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + mem2hex((char *)®isters[DIA1], ptr, + 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */ + } + break; + + case 'G': /* set the value of the CPU registers - return OK */ + { + unsigned long *newsp, psr; + + psr = registers[PSR]; + + ptr = &remcomInBuffer[1]; + hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ + hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */ + hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], + 8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + hex2mem(ptr + 72 * 4 * 2, (char *)®isters[DIA1], + 8 * 4, 0); /* DIA1, DIA2, DDA1, DDA2, DDV1, DDV2, DCR, DSR */ + + /* See if the stack pointer has moved. If so, then copy the saved + locals and ins to the new location. This keeps the window + overflow and underflow routines happy. */ + + newsp = (unsigned long *)registers[SP]; + if (sp != newsp) + sp = memcpy(newsp, sp, 16 * 4); + + /* Don't allow CWP to be modified. */ + + if (psr != registers[PSR]) + registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f); + + strcpy(remcomOutBuffer,"OK"); + } + break; + + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length)) + { + if (mem2hex((char *)addr, remcomOutBuffer, length, 1)) + break; + + strcpy (remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer,"E01"); + break; + + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* Try to read '%x,%x:'. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length) + && *ptr++ == ':') + { + if (hex2mem(ptr, (char *)addr, length, 1)) + strcpy(remcomOutBuffer, "OK"); + else + strcpy(remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer, "E02"); + break; + + case 'c': /* cAA..AA Continue at address AA..AA(optional) */ + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr)) + { + registers[PC] = addr; + registers[NPC] = addr + 4; + } + +/* Need to flush the instruction cache here, as we may have deposited a + breakpoint, and the icache probably has no way of knowing that a data ref to + some location may have changed something that is in the instruction cache. + */ + + flush_i_cache(); + return; + + /* kill the program */ + case 'k' : /* do nothing */ + break; +#if 0 + case 't': /* Test feature */ + asm (" std %f30,[%sp]"); + break; +#endif + case 'r': /* Reset */ + asm ("call 0 + nop "); + break; + +#if 0 +Disabled until we can unscrew this properly + + case 'b': /* bBB... Set baud rate to BB... */ + { + int baudrate; + extern void set_timer_3(); + + ptr = &remcomInBuffer[1]; + if (!hexToInt(&ptr, &baudrate)) + { + strcpy(remcomOutBuffer,"B01"); + break; + } + + /* Convert baud rate to uart clock divider */ + switch (baudrate) + { + case 38400: + baudrate = 16; + break; + case 19200: + baudrate = 33; + break; + case 9600: + baudrate = 65; + break; + default: + strcpy(remcomOutBuffer,"B02"); + goto x1; + } + + putpacket("OK"); /* Ack before changing speed */ + set_timer_3(baudrate); /* Set it */ + } +x1: break; +#endif + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void +breakpoint() +{ + if (!initialized) + return; + + asm(" .globl " STRINGSYM(breakinst) " + + " STRINGSYM(breakinst) ": ta 1 + "); +} + +static void +hw_breakpoint() +{ + asm(" + ta 127 + "); +} diff --git a/libgloss/sparc/sparclet-stub.c b/libgloss/sparc/sparclet-stub.c new file mode 100644 index 0000000..a462128 --- /dev/null +++ b/libgloss/sparc/sparclet-stub.c @@ -0,0 +1,1233 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for SPARC by Stu Grossman, Cygnus Support. + * Based on sparc-stub.c, it's modified for SPARClite Debug Unit hardware + * breakpoint support to create sparclite-stub.c, by Kung Hsu, Cygnus Support. + * + * This code has been extensively tested on the Fujitsu SPARClite demo board. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * P set the value of a single CPU register OK or P01 (???) + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include <string.h> +#include <signal.h> + +/************************************************************************ + * + * external low-level support routines + */ + +extern putDebugChar(); /* write a single character */ +extern getDebugChar(); /* read and return a single char */ + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 2048 + +static int initialized = 0; /* !0 means we've been initialized */ +static int remote_debug = 0; /* turn on verbose debugging */ + +extern void breakinst(); +void _cprint(); +static void hw_breakpoint(); +static void set_mem_fault_trap(); +static void get_in_break_mode(); +static unsigned char *mem2hex(); + +static const char hexchars[]="0123456789abcdef"; + +#define NUMREGS 121 + +static unsigned long saved_stack_pointer; + +/* Number of bytes of registers. */ +#define NUMREGBYTES (NUMREGS * 4) +enum regnames { G0, G1, G2, G3, G4, G5, G6, G7, + O0, O1, O2, O3, O4, O5, SP, O7, + L0, L1, L2, L3, L4, L5, L6, L7, + I0, I1, I2, I3, I4, I5, FP, I7, + + F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + + Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR, + CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR, UNUSED1, + + ASR1, ASR15, ASR17, ASR18, ASR19, ASR20, ASR21, ASR22, + /* the following not actually implemented */ + AWR0, AWR1, AWR2, AWR3, AWR4, AWR5, AWR6, AWR7, + AWR8, AWR9, AWR10, AWR11, AWR12, AWR13, AWR14, AWR15, + AWR16, AWR17, AWR18, AWR19, AWR20, AWR21, AWR22, AWR23, + AWR24, AWR25, AWR26, AWR27, AWR28, AWR29, AWR30, AWR31, + APSR +}; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +extern void trap_low(); + +asm(" + .reserve trapstack, 1000 * 4, \"bss\", 8 + + .data + .align 4 + +in_trap_handler: + .word 0 + + .text + .align 4 + +! This function is called when any SPARC trap (except window overflow or +! underflow) occurs. It makes sure that the invalid register window is still +! available before jumping into C code. It will also restore the world if you +! return from handle_exception. +! +! On entry, trap_low expects l1 and l2 to contain pc and npc respectivly. + + .globl _trap_low +_trap_low: + mov %psr, %l0 + mov %wim, %l3 + + srl %l3, %l0, %l4 ! wim >> cwp + and %l4, 0xff, %l4 ! Mask off windows 28, 29 + cmp %l4, 1 + bne window_fine ! Branch if not in the invalid window + nop + +! Handle window overflow + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + and %g1, 0xff, %g1 ! Mask off windows 28, 29 + tst %g1 + bg good_wim ! Branch if new wim is non-zero + nop + +! At this point, we need to bring a 1 into the high order bit of the wim. +! Since we don't want to make any assumptions about the number of register +! windows, we figure it out dynamically so as to setup the wim correctly. + + ! The normal way doesn't work on the sparclet as register windows + ! 28 and 29 are special purpose windows. + !not %g1 ! Fill g1 with ones + !mov %g1, %wim ! Fill the wim with ones + !nop + !nop + !nop + !mov %wim, %g1 ! Read back the wim + !inc %g1 ! Now g1 has 1 just to left of wim + !srl %g1, 1, %g1 ! Now put 1 at top of wim + + mov 0x80, %g1 ! Hack for sparclet + + ! This doesn't work on the sparclet. + !mov %g0, %wim ! Clear wim so that subsequent save + ! won't trap + andn %l3, 0xff, %l5 ! Clear wim but not windows 28, 29 + mov %l5, %wim + nop + nop + nop + +good_wim: + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l4, %g1 ! Restore %g1 + +window_fine: + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 + + set trapstack+1000*4, %sp ! Switch to trap stack + +recursive_trap: + st %l5, [%lo(in_trap_handler) + %l4] + sub %sp,(16+1+6+1+88)*4,%sp ! Make room for input & locals + ! + hidden arg + arg spill + ! + doubleword alignment + ! + registers[121] + + std %g0, [%sp + (24 + 0) * 4] ! registers[Gx] + std %g2, [%sp + (24 + 2) * 4] + std %g4, [%sp + (24 + 4) * 4] + std %g6, [%sp + (24 + 6) * 4] + + std %i0, [%sp + (24 + 8) * 4] ! registers[Ox] + std %i2, [%sp + (24 + 10) * 4] + std %i4, [%sp + (24 + 12) * 4] + std %i6, [%sp + (24 + 14) * 4] + + ! FP regs (sparclet doesn't have fpu) + + mov %y, %l4 + mov %tbr, %l5 + st %l4, [%sp + (24 + 64) * 4] ! Y + st %l0, [%sp + (24 + 65) * 4] ! PSR + st %l3, [%sp + (24 + 66) * 4] ! WIM + st %l5, [%sp + (24 + 67) * 4] ! TBR + st %l1, [%sp + (24 + 68) * 4] ! PC + st %l2, [%sp + (24 + 69) * 4] ! NPC + ! CPSR and FPSR not impl + or %l0, 0xf20, %l4 + mov %l4, %psr ! Turn on traps, disable interrupts + nop + nop + nop + +! Save coprocessor state. +! See SK/demo/hdlc_demo/ldc_swap_context.S. + + mov %psr, %l0 + sethi %hi(0x2000), %l5 ! EC bit in PSR + or %l5, %l0, %l5 + mov %l5, %psr ! enable coprocessor + nop ! 3 nops after write to %psr (needed?) + nop + nop + crdcxt %ccsr, %l1 ! capture CCSR + mov 0x6, %l2 + cwrcxt %l2, %ccsr ! set CCP state machine for CCFR + crdcxt %ccfr, %l2 ! capture CCOR + cwrcxt %l2, %ccfr ! tickle CCFR + crdcxt %ccfr, %l3 ! capture CCOBR + cwrcxt %l3, %ccfr ! tickle CCFR + crdcxt %ccfr, %l4 ! capture CCIBR + cwrcxt %l4, %ccfr ! tickle CCFR + crdcxt %ccfr, %l5 ! capture CCIR + cwrcxt %l5, %ccfr ! tickle CCFR + crdcxt %ccpr, %l6 ! capture CCPR + crdcxt %cccrcr, %l7 ! capture CCCRCR + st %l1, [%sp + (24 + 72) * 4] ! save CCSR + st %l2, [%sp + (24 + 75) * 4] ! save CCOR + st %l3, [%sp + (24 + 76) * 4] ! save CCOBR + st %l4, [%sp + (24 + 77) * 4] ! save CCIBR + st %l5, [%sp + (24 + 78) * 4] ! save CCIR + st %l6, [%sp + (24 + 73) * 4] ! save CCPR + st %l7, [%sp + (24 + 74) * 4] ! save CCCRCR + mov %l0, %psr ! restore original PSR + nop ! 3 nops after write to %psr (needed?) + nop + nop + +! End of saving coprocessor state. +! Save asr regs + +! Part of this is silly -- we should not display ASR15 or ASR19 at all. + + sethi %hi(0x01000000), %l6 + st %l6, [%sp + (24 + 81) * 4] ! ASR15 == NOP + sethi %hi(0xdeadc0de), %l6 + or %l6, %lo(0xdeadc0de), %l6 + st %l6, [%sp + (24 + 84) * 4] ! ASR19 == DEADC0DE + + rd %asr1, %l4 + st %l4, [%sp + (24 + 80) * 4] +! rd %asr15, %l4 ! must not read ASR15 +! st %l4, [%sp + (24 + 81) * 4] ! (illegal instr trap) + rd %asr17, %l4 + st %l4, [%sp + (24 + 82) * 4] + rd %asr18, %l4 + st %l4, [%sp + (24 + 83) * 4] +! rd %asr19, %l4 ! must not read asr19 +! st %l4, [%sp + (24 + 84) * 4] ! (halts the CPU) + rd %asr20, %l4 + st %l4, [%sp + (24 + 85) * 4] + rd %asr21, %l4 + st %l4, [%sp + (24 + 86) * 4] + rd %asr22, %l4 + st %l4, [%sp + (24 + 87) * 4] + +! End of saving asr regs + + call _handle_exception + add %sp, 24 * 4, %o0 ! Pass address of registers + +! Reload all of the registers that aren't on the stack + + ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx] + ldd [%sp + (24 + 2) * 4], %g2 + ldd [%sp + (24 + 4) * 4], %g4 + ldd [%sp + (24 + 6) * 4], %g6 + + ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox] + ldd [%sp + (24 + 10) * 4], %i2 + ldd [%sp + (24 + 12) * 4], %i4 + ldd [%sp + (24 + 14) * 4], %i6 + + ! FP regs (sparclet doesn't have fpu) + +! Update the coprocessor registers. +! See SK/demo/hdlc_demo/ldc_swap_context.S. + + mov %psr, %l0 + sethi %hi(0x2000), %l5 ! EC bit in PSR + or %l5, %l0, %l5 + mov %l5, %psr ! enable coprocessor + nop ! 3 nops after write to %psr (needed?) + nop + nop + + mov 0x6, %l2 + cwrcxt %l2, %ccsr ! set CCP state machine for CCFR + + ld [%sp + (24 + 72) * 4], %l1 ! saved CCSR + ld [%sp + (24 + 75) * 4], %l2 ! saved CCOR + ld [%sp + (24 + 76) * 4], %l3 ! saved CCOBR + ld [%sp + (24 + 77) * 4], %l4 ! saved CCIBR + ld [%sp + (24 + 78) * 4], %l5 ! saved CCIR + ld [%sp + (24 + 73) * 4], %l6 ! saved CCPR + ld [%sp + (24 + 74) * 4], %l7 ! saved CCCRCR + + cwrcxt %l2, %ccfr ! restore CCOR + cwrcxt %l3, %ccfr ! restore CCOBR + cwrcxt %l4, %ccfr ! restore CCIBR + cwrcxt %l5, %ccfr ! restore CCIR + cwrcxt %l6, %ccpr ! restore CCPR + cwrcxt %l7, %cccrcr ! restore CCCRCR + cwrcxt %l1, %ccsr ! restore CCSR + + mov %l0, %psr ! restore PSR + nop ! 3 nops after write to %psr (needed?) + nop + nop + +! End of coprocessor handling stuff. +! Update asr regs + + ld [%sp + (24 + 80) * 4], %l4 + wr %l4, %asr1 +! ld [%sp + (24 + 81) * 4], %l4 ! can't write asr15 +! wr %l4, %asr15 + ld [%sp + (24 + 82) * 4], %l4 + wr %l4, %asr17 + ld [%sp + (24 + 83) * 4], %l4 + wr %l4, %asr18 +! ld [%sp + (24 + 84) * 4], %l4 ! can't write asr19 +! wr %l4, %asr19 +! ld [%sp + (24 + 85) * 4], %l4 ! can't write asr20 +! wr %l4, %asr20 +! ld [%sp + (24 + 86) * 4], %l4 ! can't write asr21 +! wr %l4, %asr21 + ld [%sp + (24 + 87) * 4], %l4 + wr %l4, %asr22 + +! End of restoring asr regs + + + ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR + ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC + + restore ! Ensure that previous window is valid + save %g0, %g0, %g0 ! by causing a window_underflow trap + + mov %l0, %y + mov %l1, %psr ! Make sure that traps are disabled + ! for rett + nop ! 3 nops after write to %psr (needed?) + nop + nop + + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + dec %l5 + st %l5, [%lo(in_trap_handler) + %l4] + + jmpl %l2, %g0 ! Restore old PC + rett %l3 ! Restore old nPC +"); + +/* Convert ch from a hex digit to an int */ + +static int +hex(ch) + unsigned char ch; +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +/* scan for the sequence $<data>#<checksum> */ + +static void +getpacket(buffer) + char *buffer; +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + unsigned char ch; + + do + { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar() & 0x7f)) != '$') + ; + + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) + { + ch = getDebugChar() & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + + if (count >= BUFMAX) + continue; + + buffer[count] = 0; + + if (ch == '#') + { + xmitcsum = hex(ch = getDebugChar() & 0x7f) << 4; + xmitcsum |= hex(ch = getDebugChar() & 0x7f); + + if (checksum != xmitcsum) + putDebugChar('-'); /* failed checksum */ + else + { + putDebugChar('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar(buffer[0]); + putDebugChar(buffer[1]); + /* remove sequence chars from buffer */ + count = strlen(buffer); + for (i=3; i <= count; i++) + buffer[i-3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); +} + +/* send the packet in buffer. */ + +static void +putpacket(buffer) + unsigned char *buffer; +{ + unsigned char checksum; + int count; + unsigned char ch; + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar('$'); + checksum = 0; + count = 0; + + while (ch = buffer[count]) + { + if (! putDebugChar(ch)) + return; + checksum += ch; + count += 1; + } + + putDebugChar('#'); + putDebugChar(hexchars[checksum >> 4]); + putDebugChar(hexchars[checksum & 0xf]); + + } + while ((getDebugChar() & 0x7f) != '+'); +} + +static char remcomInBuffer[BUFMAX]; +static char remcomOutBuffer[BUFMAX]; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +static volatile int mem_err = 0; + +/* Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null), in case of mem fault, + * return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0, else treat a fault like any other fault in the stub. + */ + +static unsigned char * +mem2hex(mem, buf, count, may_fault) + unsigned char *mem; + unsigned char *buf; + int count; + int may_fault; +{ + unsigned char ch; + + set_mem_fault_trap(may_fault); + + while (count-- > 0) + { + ch = *mem++; + if (mem_err) + return 0; + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch & 0xf]; + } + + *buf = 0; + + set_mem_fault_trap(0); + + return buf; +} + +/* convert the hex array pointed to by buf into binary to be placed in mem + * return a pointer to the character AFTER the last byte written */ + +static char * +hex2mem(buf, mem, count, may_fault) + unsigned char *buf; + unsigned char *mem; + int count; + int may_fault; +{ + int i; + unsigned char ch; + + set_mem_fault_trap(may_fault); + + for (i=0; i<count; i++) + { + ch = hex(*buf++) << 4; + ch |= hex(*buf++); + *mem++ = ch; + if (mem_err) + return 0; + } + + set_mem_fault_trap(0); + + return mem; +} + +/* This table contains the mapping between SPARC hardware trap types, and + signals, which are primarily what GDB understands. It also indicates + which hardware traps we need to commandeer when initializing the stub. */ + +static struct hard_trap_info +{ + unsigned char tt; /* Trap type code for SPARClite */ + unsigned char signo; /* Signal that we map this trap into */ +} hard_trap_info[] = { + {1, SIGSEGV}, /* instruction access exception */ + {0x3b, SIGSEGV}, /* instruction access error */ + {2, SIGILL}, /* illegal instruction */ + {3, SIGILL}, /* privileged instruction */ + {4, SIGEMT}, /* fp disabled */ + {0x24, SIGEMT}, /* cp disabled */ + {7, SIGBUS}, /* mem address not aligned */ + {0x29, SIGSEGV}, /* data access exception */ + {10, SIGEMT}, /* tag overflow */ + {128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */ + {0, 0} /* Must be last */ +}; + +/* Set up exception handlers for tracing and breakpoints */ + +void +set_debug_traps() +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + exceptionHandler(ht->tt, trap_low); + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. */ + putDebugChar ('+'); + + initialized = 1; +} + +asm (" +! Trap handler for memory errors. This just sets mem_err to be non-zero. It +! assumes that %l1 is non-zero. This should be safe, as it is doubtful that +! 0 would ever contain code that could mem fault. This routine will skip +! past the faulting instruction after setting mem_err. + + .text + .align 4 + +_fltr_set_mem_err: + sethi %hi(_mem_err), %l0 + st %l1, [%l0 + %lo(_mem_err)] + jmpl %l2, %g0 + rett %l2+4 +"); + +static void +set_mem_fault_trap(enable) + int enable; +{ + extern void fltr_set_mem_err(); + mem_err = 0; + + if (enable) + exceptionHandler(0x29, fltr_set_mem_err); + else + exceptionHandler(0x29, trap_low); +} + +asm (" + .text + .align 4 + +_dummy_hw_breakpoint: + jmpl %l2, %g0 + rett %l2+4 + nop + nop +"); + +static void +set_hw_breakpoint_trap(enable) + int enable; +{ + extern void dummy_hw_breakpoint(); + + if (enable) + exceptionHandler(255, dummy_hw_breakpoint); + else + exceptionHandler(255, trap_low); +} + +static void +get_in_break_mode() +{ +#if 0 + int x; + mesg("get_in_break_mode, sp = "); + phex(&x); +#endif + set_hw_breakpoint_trap(1); + + asm(" + sethi %hi(0xff10), %l4 + or %l4, %lo(0xff10), %l4 + sta %g0, [%l4]0x1 + nop + nop + nop + "); + + set_hw_breakpoint_trap(0); +} + +/* Convert the SPARC hardware trap type code to a unix signal number. */ + +static int +computeSignal(tt) + int tt; +{ + struct hard_trap_info *ht; + + for (ht = hard_trap_info; ht->tt && ht->signo; ht++) + if (ht->tt == tt) + return ht->signo; + + return SIGHUP; /* default for things we don't know about */ +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +static int +hexToInt(char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex(**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + +/* + * This function does all command procesing for interfacing to gdb. It + * returns 1 if you should skip the instruction at the trap address, 0 + * otherwise. + */ + +static void +handle_exception (registers) + unsigned long *registers; +{ + int tt; /* Trap type */ + int sigval; + int addr; + int length; + char *ptr; + unsigned long *sp; + unsigned long dsr; + +/* First, we must force all of the windows to be spilled out */ + + asm(" + ! Ugh. sparclet has broken save + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + !save %sp, -64, %sp + save + add %fp,-64,%sp + restore + restore + restore + restore + restore + restore + restore + restore +"); + + if (registers[PC] == (unsigned long)breakinst) + { + registers[PC] = registers[NPC]; + registers[NPC] += 4; + } + sp = (unsigned long *)registers[SP]; + + tt = (registers[TBR] >> 4) & 0xff; + + /* reply to host that an exception has occurred */ + sigval = computeSignal(tt); + ptr = remcomOutBuffer; + + *ptr++ = 'T'; + *ptr++ = hexchars[sigval >> 4]; + *ptr++ = hexchars[sigval & 0xf]; + + *ptr++ = hexchars[PC >> 4]; + *ptr++ = hexchars[PC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[FP >> 4]; + *ptr++ = hexchars[FP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = hexchars[SP >> 4]; + *ptr++ = hexchars[SP & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)&sp, ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[NPC >> 4]; + *ptr++ = hexchars[NPC & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = hexchars[O7 >> 4]; + *ptr++ = hexchars[O7 & 0xf]; + *ptr++ = ':'; + ptr = mem2hex((char *)®isters[O7], ptr, 4, 0); + *ptr++ = ';'; + + *ptr++ = 0; + + putpacket(remcomOutBuffer); + + while (1) + { + remcomOutBuffer[0] = 0; + + getpacket(remcomInBuffer); + switch (remcomInBuffer[0]) + { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval & 0xf]; + remcomOutBuffer[3] = 0; + break; + + case 'd': + remote_debug = !(remote_debug); /* toggle debug flag */ + break; + + case 'g': /* return the value of the CPU registers */ + { + ptr = remcomOutBuffer; + ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ + ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */ + memset(ptr, '0', 32 * 8); /* Floating point */ + ptr = mem2hex((char *)®isters[Y], + ptr + 32 * 4 * 2, + 8 * 4, + 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ + ptr = mem2hex((char *)®isters[CCSR], + ptr, + 8 * 4, + 0); /* CCSR, CCPR, CCCRCR, CCOR, CCOBR, CCIBR, CCIR */ + ptr = mem2hex((char *)®isters[ASR1], + ptr, + 8 * 4, + 0); /* ASR1,ASR15,ASR17,ASR18,ASR19,ASR20,ASR21,ASR22 */ +#if 0 /* not implemented */ + ptr = mem2hex((char *) ®isters[AWR0], + ptr, + 32 * 4, + 0); /* Alternate Window Registers */ +#endif + } + break; + + case 'G': /* set value of all the CPU registers - return OK */ + case 'P': /* set value of one CPU register - return OK */ + { + unsigned long *newsp, psr; + + psr = registers[PSR]; + + ptr = &remcomInBuffer[1]; + + if (remcomInBuffer[0] == 'P') /* do a single register */ + { + int regno; + + if (hexToInt (&ptr, ®no) + && *ptr++ == '=') + if (regno >= L0 && regno <= I7) + hex2mem (ptr, sp + regno - L0, 4, 0); + else + hex2mem (ptr, (char *)®isters[regno], 4, 0); + else + { + strcpy (remcomOutBuffer, "P01"); + break; + } + } + else + { + hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ + hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */ + hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], + 8 * 4, 0); /* Y,PSR,WIM,TBR,PC,NPC,FPSR,CPSR */ + hex2mem(ptr + 72 * 4 * 2, (char *)®isters[CCSR], + 8 * 4, 0); /* CCSR,CCPR,CCCRCR,CCOR,CCOBR,CCIBR,CCIR */ + hex2mem(ptr + 80 * 4 * 2, (char *)®isters[ASR1], + 8 * 4, 0); /* ASR1 ... ASR22 */ +#if 0 /* not implemented */ + hex2mem(ptr + 88 * 4 * 2, (char *)®isters[AWR0], + 8 * 4, 0); /* Alternate Window Registers */ +#endif + } + /* See if the stack pointer has moved. If so, then copy the saved + locals and ins to the new location. This keeps the window + overflow and underflow routines happy. */ + + newsp = (unsigned long *)registers[SP]; + if (sp != newsp) + sp = memcpy(newsp, sp, 16 * 4); + + /* Don't allow CWP to be modified. */ + + if (psr != registers[PSR]) + registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f); + + strcpy(remcomOutBuffer,"OK"); + } + break; + + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length)) + { + if (mem2hex((char *)addr, remcomOutBuffer, length, 1)) + break; + + strcpy (remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer,"E01"); + break; + + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* Try to read '%x,%x:'. */ + + ptr = &remcomInBuffer[1]; + + if (hexToInt(&ptr, &addr) + && *ptr++ == ',' + && hexToInt(&ptr, &length) + && *ptr++ == ':') + { + if (hex2mem(ptr, (char *)addr, length, 1)) + strcpy(remcomOutBuffer, "OK"); + else + strcpy(remcomOutBuffer, "E03"); + } + else + strcpy(remcomOutBuffer, "E02"); + break; + + case 'c': /* cAA..AA Continue at address AA..AA(optional) */ + /* try to read optional parameter, pc unchanged if no parm */ + + ptr = &remcomInBuffer[1]; + if (hexToInt(&ptr, &addr)) + { + registers[PC] = addr; + registers[NPC] = addr + 4; + } + +/* Need to flush the instruction cache here, as we may have deposited a + breakpoint, and the icache probably has no way of knowing that a data ref to + some location may have changed something that is in the instruction cache. + */ + + flush_i_cache(); + return; + + /* kill the program */ + case 'k' : /* do nothing */ + break; +#if 0 + case 't': /* Test feature */ + asm (" std %f30,[%sp]"); + break; +#endif + case 'r': /* Reset */ + asm ("call 0 + nop "); + break; + +#if 0 +Disabled until we can unscrew this properly + + case 'b': /* bBB... Set baud rate to BB... */ + { + int baudrate; + extern void set_timer_3(); + + ptr = &remcomInBuffer[1]; + if (!hexToInt(&ptr, &baudrate)) + { + strcpy(remcomOutBuffer,"B01"); + break; + } + + /* Convert baud rate to uart clock divider */ + switch (baudrate) + { + case 38400: + baudrate = 16; + break; + case 19200: + baudrate = 33; + break; + case 9600: + baudrate = 65; + break; + default: + strcpy(remcomOutBuffer,"B02"); + goto x1; + } + + putpacket("OK"); /* Ack before changing speed */ + set_timer_3(baudrate); /* Set it */ + } +x1: break; +#endif + } /* switch */ + + /* reply to the request */ + putpacket(remcomOutBuffer); + } +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void +breakpoint() +{ + if (!initialized) + return; + + asm(" .globl _breakinst + + _breakinst: ta 1 + "); +} + +static void +hw_breakpoint() +{ + asm(" + ta 127 + "); +} + +#if 0 /* experimental and never finished, left here for reference */ +static void +splet_temp(void) +{ + asm(" sub %sp,(16+1+6+1+121)*4,%sp ! Make room for input & locals + ! + hidden arg + arg spill + ! + doubleword alignment + ! + registers[121] + +! Leave a trail of breadcrumbs! (save register save area for debugging) + mov %sp, %l0 + add %l0, 24*4, %l0 + sethi %hi(_debug_registers), %l1 + st %l0, [%lo(_debug_registers) + %l1] + +! Save the Alternate Register Set: (not implemented yet) +! To save the Alternate Register set, we must: +! 1) Save the current SP in some global location. +! 2) Swap the register sets. +! 3) Save the Alternate SP in the Y register +! 4) Fetch the SP that we saved in step 1. +! 5) Use that to save the rest of the regs (not forgetting ASP in Y) +! 6) Restore the Alternate SP from Y +! 7) Swap the registers back. + +! 1) Copy the current stack pointer to global _SAVED_STACK_POINTER: + sethi %hi(_saved_stack_pointer), %l0 + st %sp, [%lo(_saved_stack_pointer) + %l0] + +! 2) Swap the register sets: + mov %psr, %l1 + sethi %hi(0x10000), %l2 + xor %l1, %l2, %l1 + mov %l1, %psr + nop ! 3 nops after write to %psr (needed?) + nop + nop + +! 3) Save Alternate L0 in Y + wr %l0, 0, %y + +! 4) Load former SP into alternate SP, using L0 + sethi %hi(_saved_stack_pointer), %l0 + or %lo(_saved_stack_pointer), %l0, %l0 + swap [%l0], %sp + +! 4.5) Restore alternate L0 + rd %y, %l0 + +! 5) Save the Alternate Window Registers + st %r0, [%sp + (24 + 88) * 4] ! AWR0 + st %r1, [%sp + (24 + 89) * 4] ! AWR1 + st %r2, [%sp + (24 + 90) * 4] ! AWR2 + st %r3, [%sp + (24 + 91) * 4] ! AWR3 + st %r4, [%sp + (24 + 92) * 4] ! AWR4 + st %r5, [%sp + (24 + 93) * 4] ! AWR5 + st %r6, [%sp + (24 + 94) * 4] ! AWR6 + st %r7, [%sp + (24 + 95) * 4] ! AWR7 + st %r8, [%sp + (24 + 96) * 4] ! AWR8 + st %r9, [%sp + (24 + 97) * 4] ! AWR9 + st %r10, [%sp + (24 + 98) * 4] ! AWR10 + st %r11, [%sp + (24 + 99) * 4] ! AWR11 + st %r12, [%sp + (24 + 100) * 4] ! AWR12 + st %r13, [%sp + (24 + 101) * 4] ! AWR13 +! st %r14, [%sp + (24 + 102) * 4] ! AWR14 (SP) + st %r15, [%sp + (24 + 103) * 4] ! AWR15 + st %r16, [%sp + (24 + 104) * 4] ! AWR16 + st %r17, [%sp + (24 + 105) * 4] ! AWR17 + st %r18, [%sp + (24 + 106) * 4] ! AWR18 + st %r19, [%sp + (24 + 107) * 4] ! AWR19 + st %r20, [%sp + (24 + 108) * 4] ! AWR20 + st %r21, [%sp + (24 + 109) * 4] ! AWR21 + st %r22, [%sp + (24 + 110) * 4] ! AWR22 + st %r23, [%sp + (24 + 111) * 4] ! AWR23 + st %r24, [%sp + (24 + 112) * 4] ! AWR24 + st %r25, [%sp + (24 + 113) * 4] ! AWR25 + st %r26, [%sp + (24 + 114) * 4] ! AWR26 + st %r27, [%sp + (24 + 115) * 4] ! AWR27 + st %r28, [%sp + (24 + 116) * 4] ! AWR28 + st %r29, [%sp + (24 + 117) * 4] ! AWR29 + st %r30, [%sp + (24 + 118) * 4] ! AWR30 + st %r31, [%sp + (24 + 119) * 4] ! AWR21 + +! Get the Alternate PSR (I hope...) + + rd %psr, %l2 + st %l2, [%sp + (24 + 120) * 4] ! APSR + +! Don't forget the alternate stack pointer + + rd %y, %l3 + st %l3, [%sp + (24 + 102) * 4] ! AWR14 (SP) + +! 6) Restore the Alternate SP (saved in Y) + + rd %y, %o6 + + +! 7) Swap the registers back: + + mov %psr, %l1 + sethi %hi(0x10000), %l2 + xor %l1, %l2, %l1 + mov %l1, %psr + nop ! 3 nops after write to %psr (needed?) + nop + nop +"); +} + +#endif diff --git a/libgloss/sparc/sparclite.h b/libgloss/sparc/sparclite.h new file mode 100644 index 0000000..0f14d51 --- /dev/null +++ b/libgloss/sparc/sparclite.h @@ -0,0 +1,81 @@ +/* SPARClite defs + * + * Copyright (c) 1995 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. + */ + +/* Macros for reading and writing to arbitrary address spaces. Note that ASI + must be a constant (sorry, but the SPARC can only specify ASIs as part of an + instruction. */ + +#define read_asi(ASI, LOC) \ + ({ \ + unsigned int val; \ + __asm__ volatile ("lda [%r1]%2,%0" : "=r" (val) : "rJ" (LOC), "I" (ASI)); \ + val; \ + }) + +#define write_asi(ASI, LOC, VAL) \ + __asm__ volatile ("sta %0,[%r1]%2" : : "r" (VAL), "rJ" (LOC), "I" (ASI)) + +/* Use this when modifying registers that cause memory to be modified. This + will cause GCC to reload all values after this point. */ + +#define write_asi_volatile(ASI, LOC, VAL) \ + __asm__ volatile ("sta %0,[%r1]%2" : : "r" (VAL), "rJ" (LOC), "I" (ASI) \ + : "memory") + +/* Read the PSR (processor state register). */ + +#define read_psr() \ + ({ \ + unsigned int psr; \ + __asm__ ("mov %%psr, %0" : "=r" (psr)); \ + psr; \ + }) + +/* Write the PSR. */ + +#define write_psr(VAL) \ + __asm__ ("mov %0, %%psr \n nop \n nop \n nop" : : "r" (VAL)) + +/* Read the specified Ancillary State Register. */ + +#define read_asr(REG) read_asr1(REG) +#define read_asr1(REG) \ + ({ \ + unsigned int val; \ + __asm__ ("rd %%asr" #REG ",%0" : "=r" (val)); \ + val; \ + }) + +/* Write the specified Ancillary State Register. */ + +#define write_asr(REG, VAL) write_asr1(REG, VAL) +#define write_asr1(REG, VAL) \ + __asm__ ("wr %0, 0, %%asr" #REG : : "r" (VAL)) + +/* Set window size for window overflow and underflow trap handlers. Better to + do this at at compile time than to calculate them at compile time each time + we get a window overflow/underflow trap. */ + +#ifdef SL933 + asm ("__WINSIZE=6"); +#else + asm ("__WINSIZE=8"); +#endif + +#define PSR_INIT 0x10c0 /* Disable traps, set s and ps */ +#define TBR_INIT 0 +#define WIM_INIT 2 +#define STACK_SIZE 16 * 1024 + diff --git a/libgloss/sparc/sysc-701.c b/libgloss/sparc/sysc-701.c new file mode 100644 index 0000000..191a08a --- /dev/null +++ b/libgloss/sparc/sysc-701.c @@ -0,0 +1,55 @@ +/* more sparclet syscall support (the rest is in crt0-701.S). */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +int +fstat(int _fd, struct stat* _sbuf) +{ + errno = ENOSYS; + return -1; +} + +int +isatty(int fd) +{ + if (fd < 0) + { + errno = EBADF; + return -1; + } + return fd <= 2; +} + +int +getpid() +{ + return 1; +} + +int +kill(int pid) +{ + /* if we knew how to nuke the board, we would... */ + return 0; +} + +int +lseek(int _fd, off_t offset, int whence) +{ + errno = ENOSYS; + return -1; +} + +extern char end; +char* +sbrk (int incr) +{ + static char* base; + char *b; + if(!base) base = &end; + b = base; + base += incr; + return b; +} diff --git a/libgloss/sparc/syscalls.c b/libgloss/sparc/syscalls.c new file mode 100644 index 0000000..01ba501 --- /dev/null +++ b/libgloss/sparc/syscalls.c @@ -0,0 +1,85 @@ +/* Copyright (c) 1995 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. + * + * fake unix routines for sparclite and remote debugger + * Many of these routines just substitute an appropriate error status, + * if you want some kind of file system access, you'll have to fill them in... + * sbrk on the other hand is functional (malloc uses it) but it doesn't do + * any checking for lack of memory. + * kill and _exit could get more real implementations, as well. + */ + +#include <sys/stat.h> + +int +fstat(int _fd, struct stat* _sbuf) +{ + /* this is used in a few places in stdio... */ + /* just error, so they assume a pipe */ + return -1; +} + +int +isatty(int _fd) +{ + return 1; +} + +int +close(int _fd) +{ + /* return value usually ignored anyhow */ + return 0; +} + +int +open(char *filename) +{ + /* always fail */ + return -1; +} + +int +getpid() { + return 1; +} + +int +kill(int pid) { + /* if we knew how to nuke the board, we would... */ + return 0; +} + +void +_exit(int status) { + /* likewise... */ + return; +} + +int +lseek(int _fd, off_t offset, int whence) +{ + /* nothing is ever seekable */ + return -1; +} + +extern char end; +char* +sbrk(int incr) +{ + static char* base; + char *b; + if(!base) base = &end; + b = base; + base += incr; + return b; +} diff --git a/libgloss/sparc/test.c b/libgloss/sparc/test.c new file mode 100644 index 0000000..fc443a8 --- /dev/null +++ b/libgloss/sparc/test.c @@ -0,0 +1,69 @@ +#include "debug.h" + +char hextab[] = "0123456789abcdef"; + +int +foo(arg) + int arg; +{ + return arg+1; +} + +int +fact (i) + int i; +{ + if (i == 1) + return 1; + else + return i * fact ( i - 1); +} + +main() +{ + unsigned char c; + int num; + char foo[100]; + +#if 0 + set_debug_level(2); + + cache_on(); +#endif + + set_debug_traps(); + breakpoint(); + + print("Got to here\r\n"); + + while (1) { + c = inbyte(); + if (c == 'c') + break; + + if (c == 'd') { + set_debug_traps(); + breakpoint(); + break; + } + + print("echo "); + outbyte(c); + print("\r\n"); + } + + print("Hello world\r\n"); + + while (1) { + c = inbyte(); + + if ((c & 0x7f) == 4) + break; + + print("Char is "); + outbyte (c); + print("\r\n"); + } + + print("I escaped!\r\n"); +} diff --git a/libgloss/sparc/traps.S b/libgloss/sparc/traps.S new file mode 100644 index 0000000..b3cc966 --- /dev/null +++ b/libgloss/sparc/traps.S @@ -0,0 +1,651 @@ +/* + * Copyright (c) 1995, 1996, 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. + */ + +#include "asm.h" +#include "slite.h" + + .text + .align 4 + +/* + * The trap table has to be the first code in a boot PROM. But because + * the Memory Configuration comes up thinking we only have 4K of PROM, we + * cannot have a full trap table and still have room left over to + * reprogram the Memory Configuration register correctly. This file + * uses an abbreviated trap which has every entry which might be used + * before RTEMS installs its own trap table. + */ + .globl _trap_table +_trap_table: + TRAP(SYM(ercinit)); ! 00 reset trap + BAD_TRAP; ! 01 instruction access exception + TRAP(SYM(no_fpu)); ! 02 illegal instruction + BAD_TRAP; ! 03 privileged instruction + BAD_TRAP; ! 04 fp disabled + TRAP(SYM(win_overflow)); ! 05 window overflow + TRAP(SYM(win_underflow)); ! 06 window underflow + BAD_TRAP; ! 07 memory address not aligned + BAD_TRAP; ! 08 fp exception + BAD_TRAP; ! 09 data access exception + BAD_TRAP; ! 0A tag overflow + + /* Trap levels from 0B to 0x10 are not defined (used for MEC init) */ + +SYM(ercinit): + sethi %hi(_ERC32_MEC), %g1 ! 0B + sethi %hi(0x001C1000), %g2 + or %g1,%lo(0x001C1000),%g1 + st %g2, [%g1 + 0x10] + st %g0, [%g1 + 0x18] ! 0C + nop + nop + nop + + TRAP(SYM(hard_reset)); ! 0D undefined + BAD_TRAP; ! 0E undefined + BAD_TRAP; ! 0F undefined + BAD_TRAP; ! 10 undefined + + /* + * ERC32 defined traps + */ + + BAD_TRAP; ! 11 masked errors + BAD_TRAP; ! 12 external 1 + BAD_TRAP; ! 13 external 2 + BAD_TRAP; ! 14 UART A RX/TX + BAD_TRAP; ! 15 UART B RX/TX + BAD_TRAP; ! 16 correctable memory error + BAD_TRAP; ! 17 UART error + BAD_TRAP; ! 18 DMA access error + BAD_TRAP; ! 19 DMA timeout + BAD_TRAP; ! 1A external 3 + BAD_TRAP; ! 1B external 4 + BAD_TRAP; ! 1C general purpose timer + BAD_TRAP; ! 1D real time clock + BAD_TRAP; ! 1E external 5 + BAD_TRAP; ! 1F watchdog timeout + + + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 undefined + BAD_TRAP; ! 24 cp_disabled + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 25 - 27 undefined + BAD_TRAP; ! 28 cp_exception + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 29 - 2B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F undefined + + /* + * Software traps + * + * NOTE: At the risk of being redundant... this is not a full + * table. The setjmp on the SPARC requires a window flush trap + * handler and RTEMS will preserve the entries that were + * installed before. + */ + + SOFT_TRAP; ! 80 +#if 0 + SOFT_TRAP; ! 81 +#else + TRAP(SYM(trap_low)) ! 81 +#endif + SOFT_TRAP; ! 82 + TRAP(SYM(win_flush)); ! 83 flush windows SW trap + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88 - 8B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - AB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! FC - FF + +/* + * Startup code for standalone system. Wash IU and FPU (if present) + * registers. The registers have to be written to initiate the parity + * bits. + */ + .globl SYM(hard_reset) +SYM(hard_reset): + + sethi %hi(0x01FE0),%o0 + or %o0,%lo(0x01FE0),%o0 + mov %o0, %psr ! Set valid PSR + nop + + mov %g0, %wim ! Set window invalid mask register + mov %g0, %y ! Init Y-register + nop + sethi %hi(SYM(hard_reset)), %g1 + + mov %g1, %tbr ! Set TBR + sethi %hi(SP_INIT),%sp + or %g0, 1, %o0 + ld [%g0], %f0 ! Check if FPU is present + + tst %o0 + bz fixiu + nop + ba fixfpu + +! FPU disabled trap address + + clr %i0 + jmpl %l2, %g0 + rett %l2 + 4 + nop + + +! Wash register files (fix for 90C601E & 90C602E) + +fixfpu: + + ld [%g0], %f0 + ld [%g0], %f1 + ld [%g0], %f2 + ld [%g0], %f3 + ld [%g0], %f4 + ld [%g0], %f5 + ld [%g0], %f6 + ld [%g0], %f7 + ld [%g0], %f8 + ld [%g0], %f9 + ld [%g0], %f10 + ld [%g0], %f11 + ld [%g0], %f12 + ld [%g0], %f13 + ld [%g0], %f14 + ld [%g0], %f15 + ld [%g0], %f16 + ld [%g0], %f17 + ld [%g0], %f18 + ld [%g0], %f19 + ld [%g0], %f20 + ld [%g0], %f21 + ld [%g0], %f22 + ld [%g0], %f23 + ld [%g0], %f24 + ld [%g0], %f25 + ld [%g0], %f26 + ld [%g0], %f27 + ld [%g0], %f28 + ld [%g0], %f29 + ld [%g0], %f30 + ld [%g0], %f31 + +fixiu: + clr %g1 + clr %g2 + clr %g3 + clr %g4 + clr %g5 + clr %g6 + clr %g7 + set 8,%g1 +wl0: + clr %i0 + clr %i1 + clr %i2 + clr %i3 + clr %i4 + clr %i5 + clr %i6 + clr %i7 + clr %l0 + clr %l1 + clr %l2 + clr %l3 + clr %l4 + clr %l5 + clr %l6 + clr %l7 + save + subcc %g1, 1, %g1 + bne wl0 + nop + +! +! Start the real-time clock with a tick of 150 clocks +! + +rtc: + + set 0x1f80000, %l0 ! MEC register base + set 149, %l1 + st %l1, [%l0 + 0x84] ! RTC scaler = 149 + set 0x0d00, %l1 + st %l1, [%l0 + 0x98] ! Start RTC + + st %g0, [%l0 + 0x64] ! Disable watchdog for now + ld [%l0], %g1 + or %g1, 1, %g1 + st %g1, [%l0] ! Enable power-down mode + +_init: + set PSR_INIT, %g1 ! Initialize psr + mov %g1, %psr + set WIM_INIT, %g1 ! Initialize WIM + mov %g1, %wim + set _trap_table, %g1 ! Initialize TBR + mov %g1, %tbr + nop;nop;nop + + set PSR_INIT, %g1 + wr %g1, 0x20, %psr ! enable traps + nop; nop; nop; + + call SYM(start) + nop + +/* + * Register window overflow handler. Come here when save would move us + * into the invalid window. This routine runs with traps disabled, and + * must be careful not to touch the condition codes, as PSR is never + * restored. + * + * We are called with %l0 = wim, %l1 = pc, %l2 = npc + */ + .globl SYM(win_overflow) +SYM(win_overflow): + mov %g1, %l3 ! Save g1, we use it to hold the wim + srl %l0, 1, %g1 ! Rotate wim right + sll %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0 + or %l0, %g1, %g1 + + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + nop + nop + nop + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l3, %g1 ! Restore %g1 + + jmpl %l1, %g0 + rett %l2 + +/* + * Register window underflow handler. Come here when restore would move us + * into the invalid window. This routine runs with traps disabled, and + * must be careful not to touch the condition codes, as PSR is never + * restored. + * + * We are called with %l0 = wim, %l1 = pc, %l2 = npc + */ + .globl SYM(win_underflow) +SYM(win_underflow): + sll %l0, 1, %l3 ! Rotate wim left + srl %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0 + or %l0, %l3, %l0 + + mov %l0, %wim ! Install the new wim + + restore ! Users window + restore ! His callers window + + ldd [%sp + 0 * 4], %l0 ! restore L & I registers + ldd [%sp + 2 * 4], %l2 + ldd [%sp + 4 * 4], %l4 + ldd [%sp + 6 * 4], %l6 + + ldd [%sp + 8 * 4], %i0 + ldd [%sp + 10 * 4], %i2 + ldd [%sp + 12 * 4], %i4 + ldd [%sp + 14 * 4], %i6 + + save %g0, %g0, %g0 ! Back to trap window + save %g0, %g0, %g0 + + jmpl %l1, %g0 + rett %l2 + +/* + * Register window flush handler, triggered by a "ta 3" instruction. + * We are called with %l0 = wim, %l1 = pc, %l2 = npc + */ + .globl SYM(win_flush) +SYM(win_flush): + mov %psr, %l0 + or %l0,0xf00,%l3 ! Disable interrupts + mov %l3,%psr + nop + nop + nop + mov %wim, %l3 + + srl %l3, %l0, %l4 ! wim >> cwp + cmp %l4, 1 + bne flush_window_fine ! Branch if not in the invalid window + nop + +/* Handle window overflow. We can't trap here. */ + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + sll %l3, NUMBER_OF_REGISTER_WINDOWS - 1, %l3 + or %l3, %g1, %g1 + mov %g0, %wim ! Clear wim so that subsequent save + nop ! wont trap + nop + nop + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l4, %g1 ! Restore %g1 + +flush_window_fine: + mov %psr,%l5 ! enable traps + or %l5,0x20,%l5 + mov %l5, %psr + nop + nop + nop + + set save_buf,%l5 + st %l2,[%l5] + + ! The stack pointer currently contains a bogus value [when a trap + ! occurs CWP is decremented and points to an unused window]. + ! Give it something useful before we flush every window. + ! This does what a "save %sp,-64,$sp" would, except that CWP has + ! already been decremented. + add %fp, -64, %sp + + save %sp, -64, %sp ! Flush user register window to stack + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + save %sp, -64, %sp + restore + restore + restore + restore + restore + restore + restore + restore + + restore ! Make sure we have a valid window + save %g0, %g0, %g0 + + set save_buf, %l2 ! Get our return address back + ld [%l2],%l2 + + mov %psr,%l5 ! disable traps for rett + andn %l5,0x20,%l5 + mov %l5,%psr + nop + nop + nop + + jmpl %l2, %g0 + rett %l2+4 + +/* + * Read the TBR. + */ + .globl SYM(rdtbr) +SYM(rdtbr): + mov %tbr, %o0 + nop + retl + nop + +/* + * Read the psr + */ + .globl SYM(read_psr) +SYM(read_psr): + mov %psr, %o0 + nop + retl + nop + +/* + * Write the PSR. + */ + + .globl SYM(write_psr) +SYM(write_psr): + mov %i0, %psr + nop + nop + nop + retl + nop +/* + * Come here when no fpu exists. This just skips the offending + * instruction. + */ + .globl SYM(no_fpu) +SYM(no_fpu): + jmpl %l2, %g0 + rett %l2+4 + + .globl SYM(fltr_proto) + .align 4 +SYM(fltr_proto): ! First level trap routine prototype + sethi 0, %l0 + jmpl 0+%l0, %g0 + nop + nop + +/* + * Trap handler for memory errors. This just sets mem_err to be + * non-zero. It assumes that l1 is non-zero. This should be safe, + * as it is doubtful that 0 would ever contain code that could mem + * fault. This routine will skip past the faulting instruction after + * setting mem_err. + */ + .globl SYM(fltr_set_mem_err) +SYM(fltr_set_mem_err): + sethi %hi(SYM(mem_err)), %l0 + st %l1, [%l0 + %lo(SYM(mem_err))] + jmpl %l2, %g0 + rett %l2+4 + + .data + .align 4 + .ascii "DaTa" + .long SYM(sdata) +in_trap_handler: + .word 0 +save_buf: + .word 0 /* place to save %g1 */ + .word 0 /* place to save %g2 */ + + .text + .align 4 + +/* + * This function is called when any SPARC trap (except window overflow + * or underflow) occurs. It makes sure that the invalid register + * window is still available before jumping into C code. It will also + * restore the world if you return from handle_exception. + */ + .globl SYM(trap_low) +SYM(trap_low): + mov %psr, %l0 + mov %wim, %l3 + + srl %l3, %l0, %l4 ! wim >> cwp + cmp %l4, 1 + bne window_fine ! Branch if not in the invalid window + nop + + mov %g1, %l4 ! Save g1, we use it to hold the wim + srl %l3, 1, %g1 ! Rotate wim right + sll %l3, 8-1, %l5 + or %l5, %g1, %g1 + + save %g0, %g0, %g0 ! Slip into next window + mov %g1, %wim ! Install the new wim + + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + + restore ! Go back to trap window. + mov %l4, %g1 ! Restore g1 + +window_fine: + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + tst %l5 + bg recursive_trap + inc %l5 + + /* use the stack we set in the linker script */ + sethi %hi(__trap_stack), %l6 + or %l6,%lo(__trap_stack),%l6 + mov %l6, %sp ! set the stack pointer + +recursive_trap: + st %l5, [%lo(in_trap_handler) + %l4] + + sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals + ! + hidden arg + arg spill + ! + doubleword alignment + ! + registers[72] local var + + std %g0, [%sp + (24 + 0) * 4] ! registers[Gx] + std %g2, [%sp + (24 + 2) * 4] + std %g4, [%sp + (24 + 4) * 4] + std %g6, [%sp + (24 + 6) * 4] + + std %i0, [%sp + (24 + 8) * 4] ! registers[Ox] + std %i2, [%sp + (24 + 10) * 4] + std %i4, [%sp + (24 + 12) * 4] + std %i6, [%sp + (24 + 14) * 4] + ! F0->F31 not implemented + mov %y, %l4 + mov %tbr, %l5 + st %l4, [%sp + (24 + 64) * 4] ! Y + st %l0, [%sp + (24 + 65) * 4] ! PSR + st %l3, [%sp + (24 + 66) * 4] ! WIM + st %l5, [%sp + (24 + 67) * 4] ! TBR + st %l1, [%sp + (24 + 68) * 4] ! PC + st %l2, [%sp + (24 + 69) * 4] ! NPC + ! CPSR and FPSR not implemented + + or %l0, 0xf20, %l4 + mov %l4, %psr ! Turn on traps, disable interrupts + + call SYM(handle_exception) + add %sp, 24 * 4, %o0 ! Pass address of registers + +/* Reload all of the registers that aren't on the stack */ + + ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx] + ldd [%sp + (24 + 2) * 4], %g2 + ldd [%sp + (24 + 4) * 4], %g4 + ldd [%sp + (24 + 6) * 4], %g6 + + ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox] + ldd [%sp + (24 + 10) * 4], %i2 + ldd [%sp + (24 + 12) * 4], %i4 + ldd [%sp + (24 + 14) * 4], %i6 + + ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR + ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC + + restore ! Ensure that previous window is valid + save %g0, %g0, %g0 ! by causing a window_underflow trap + + mov %l0, %y + mov %l1, %psr ! Make sure that traps are disabled + ! for rett + + sethi %hi(in_trap_handler), %l4 + ld [%lo(in_trap_handler) + %l4], %l5 + dec %l5 + st %l5, [%lo(in_trap_handler) + %l4] + + jmpl %l2, %g0 ! Restore old PC + rett %l3 ! Restore old nPC + + diff --git a/libgloss/sparc/tsc701.ld b/libgloss/sparc/tsc701.ld new file mode 100644 index 0000000..bc6cd73 --- /dev/null +++ b/libgloss/sparc/tsc701.ld @@ -0,0 +1,55 @@ +/* must compile with -nostdlib option */ +OUTPUT_FORMAT("a.out-sunos-big", "a.out-sunos-big", + "a.out-sparc-little") +OUTPUT_ARCH(sparc) +SEARCH_DIR(/usr/local/sparclet-aout/lib) +PROVIDE (__stack = 0); +ENTRY (start) +STARTUP (crt0-701.o) +GROUP (libsplet701.a libc.a libgcc.a) +SECTIONS +{ + /* Sparcmon likes to load programs starting at this address. */ + . = 0x12010000; + .text : + { + CREATE_OBJECT_SYMBOLS + *(.text) + /* The next six sections are for SunOS dynamic linking. The order + is important. */ + *(.dynrel) + *(.hash) + *(.dynsym) + *(.dynstr) + *(.rules) + *(.need) + _etext = .; + __etext = .; + } + .data : + { + /* The first three sections are for SunOS dynamic linking. */ + *(.dynamic) + *(.got) + *(.plt) + *(.data) + *(.linux-dynamic) /* For Linux dynamic linking. */ + CONSTRUCTORS + _edata = .; + __edata = .; + } + .bss : + { + __bss_start = .; + *(.bss) + *(COMMON) + _end = ALIGN(4) ; + __end = ALIGN(4) ; + } + /* This is the value that Sparcmon assigns to the SP at reset, minus 4K. */ + PROVIDE(___stack = 0x123ef000); + PROVIDE(__stack = 0x123ef000); + /* Provide 4K area for copying the trap vectors from ROM to RAM. */ + PROVIDE(___trap_vectors = 0x123f0000); + PROVIDE(__trap_vectors = 0x123f0000); +} |