20000317 sourceware import
This commit is contained in:
233
libgloss/mips/Makefile.in
Normal file
233
libgloss/mips/Makefile.in
Normal file
@ -0,0 +1,233 @@
|
||||
# Copyright (c) 1995, 1996, 1997, 1998, 1999 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.
|
||||
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
objdir = .
|
||||
srcroot = $(srcdir)/../..
|
||||
objroot = $(objdir)/../..
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
host_alias = @host_alias@
|
||||
target_alias = @target_alias@
|
||||
program_transform_name = @program_transform_name@
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
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@
|
||||
AS = `if [ -f ${objroot}/../gas/as.new ] ; \
|
||||
then echo ${objroot}/../gas/as.new ; \
|
||||
else echo as ; fi`
|
||||
|
||||
AR = @AR@
|
||||
|
||||
#LD = @LD@
|
||||
LD = `if [ -f ${objroot}/../ld/ld.new ] ; \
|
||||
then echo ${objroot}/../ld/ld.new ; \
|
||||
else echo ld ; fi`
|
||||
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
OBJDUMP = `if [ -f ${objroot}/../binutils/objdump ] ; \
|
||||
then echo ${objroot}/../binutils/objdump ; \
|
||||
else t='$(program_transform_name)'; echo objdump | sed -e $$t ; fi`
|
||||
OBJCOPY = `if [ -f ${objroot}/../binutils/objcopy ] ; \
|
||||
then echo ${objroot}/../binutils/objcopy ; \
|
||||
else t='$(program_transform_name)'; echo objcopy | sed -e $$t ; fi`
|
||||
|
||||
CRT0 = @crt0@
|
||||
PCRT0 = @pcrt0@
|
||||
GENOBJS = syscalls.o fstat.o getpid.o isatty.o kill.o \
|
||||
lseek.o print.o putnum.o stat.o unlink.o
|
||||
IDTOBJS = idtmon.o @part_specific_obj@ ${GENOBJS}
|
||||
PMONOBJS = pmon.o @part_specific_obj@ ${GENOBJS}
|
||||
LSIOBJS = lsipmon.o @part_specific_obj@ ${GENOBJS}
|
||||
DVEOBJS = open.o close.o dvemon.o read.o write.o @part_specific_obj@ ${GENOBJS}
|
||||
JMR3904OBJS = open.o close.o jmr3904-io.o read.o write.o \
|
||||
@part_specific_obj@ ${GENOBJS}
|
||||
|
||||
# Nullmon cannot support read and write, but the test cases pull them in via libs
|
||||
NULLMONOBJS = nullmon.o @part_specific_obj@ ${GENOBJS}
|
||||
|
||||
CFLAGS = -g
|
||||
|
||||
GCC_LDFLAGS = `if [ -d ${objroot}/../gcc ] ; \
|
||||
then echo -L${objroot}/../gcc ; fi`
|
||||
|
||||
SCRIPTS = @script_list@
|
||||
BSP = @bsp_list@
|
||||
|
||||
PART_SPECIFIC_DEFINES = @part_specific_defines@
|
||||
|
||||
# Host specific makefile fragment comes in here.
|
||||
@host_makefile_frag@
|
||||
|
||||
#
|
||||
# build a test program for each target board. Just trying to get
|
||||
# it to link is a good test, so we ignore all the errors for now.
|
||||
#
|
||||
|
||||
all: ${CRT0} ${PCRT0} test.o ${BSP}
|
||||
|
||||
#
|
||||
# here's where we build the board support packages for each target
|
||||
#
|
||||
mipsidt.o: $(IDTOBJS)
|
||||
${LD} -r $(IDTOBJS) -o $@
|
||||
|
||||
mipspmon.o: $(PMONOBJS)
|
||||
${LD} -r $(PMONOBJS) -o $@
|
||||
|
||||
mipslsi.o: $(PMONOBJS)
|
||||
${LD} -r $(LSIOBJS) -o $@
|
||||
|
||||
libidt.a: $(IDTOBJS)
|
||||
${AR} ${ARFLAGS} $@ $(IDTOBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
libpmon.a: $(PMONOBJS)
|
||||
${AR} ${ARFLAGS} $@ $(PMONOBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
liblsi.a: $(LSIOBJS)
|
||||
${AR} ${ARFLAGS} $@ $(LSIOBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
libdve.a: $(DVEOBJS)
|
||||
${AR} ${ARFLAGS} $@ $(DVEOBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
libjmr3904.a: $(JMR3904OBJS)
|
||||
${AR} ${ARFLAGS} $@ $(JMR3904OBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
# nullmon.a , This is what you want if you want crt0 but NO mon services
|
||||
# Supports GDB sim testing, board bringups, ICE operation.
|
||||
libnullmon.a: $(NULLMONOBJS)
|
||||
${AR} ${ARFLAGS} $@ $(NULLMONOBJS)
|
||||
${RANLIB} $@
|
||||
|
||||
|
||||
# compile a fully linked binary. 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.
|
||||
|
||||
test: $(OBJS) ${BSP} pmon-test idt-test
|
||||
@echo Done...
|
||||
|
||||
dtor.o: $(srcdir)/dtor.C
|
||||
$(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) -o $@ -c $<
|
||||
dtor.x: dtor.o ${CRT0} ${srcdir}/pmon.ld Makefile libpmon.a
|
||||
${CC} $(CFLAGS_FOR_TARGET) -L${srcdir} -L${objdir} \
|
||||
dtor.o -o $@ $(NEWLIB_LDFLAGS) -N -Wl,-Tpmon.ld
|
||||
|
||||
pmon-test.x: test.o ${CRT0} Makefile libpmon.a
|
||||
${CC} $(CFLAGS_FOR_TARGET) -L${srcdir} -L${objdir} \
|
||||
test.o -o $@ $(NEWLIB_LDFLAGS) -Wl,-Tpmon.ld
|
||||
pmon-test.srec: pmon-test.x
|
||||
$(OBJCOPY) -O srec pmon-test.x $@
|
||||
pmon-test.dis: pmon-test.x
|
||||
@rm -fr pmon-test.dis
|
||||
$(OBJDUMP) -d pmon-test.x > $@
|
||||
pmon-test: pmon-test.srec pmon-test.dis
|
||||
|
||||
idt-test.x: test.o ${CRT0} Makefile libidt.a
|
||||
${CC} $(CFLAGS_FOR_TARGET) -L${srcdir} -L${objdir} \
|
||||
test.o -o $@ $(NEWLIB_LDFLAGS) -Wl,-Tidt.ld
|
||||
idt-test.srec: idt-test.x
|
||||
$(OBJCOPY) -O srec idt-test.x $@
|
||||
idt-test.dis: idt-test.x
|
||||
@rm -fr idt-test.dis
|
||||
$(OBJDUMP) -d idt-test.x > $@
|
||||
idt-test: idt-test.srec idt-test.dis
|
||||
|
||||
doc:
|
||||
|
||||
clean mostlyclean:
|
||||
rm -f a.out core *.i *~ *.o *-test *.srec *.dis *.map *.x
|
||||
|
||||
distclean maintainer-clean realclean: clean
|
||||
rm -f Makefile config.status a.out
|
||||
|
||||
.PHONY: install info install-info clean-info
|
||||
install:
|
||||
if test "x$(CRT0)" != x ; then \
|
||||
$(INSTALL_PROGRAM) $(CRT0) $(tooldir)/lib${MULTISUBDIR}/$(CRT0) ; \
|
||||
fi
|
||||
if test "x$(PCRT0)" != x ; then \
|
||||
$(INSTALL_PROGRAM) $(PCRT0) $(tooldir)/lib${MULTISUBDIR}/$(PCRT0) ; \
|
||||
fi
|
||||
@for bsp in ${BSP}; do\
|
||||
$(INSTALL_PROGRAM) $${bsp} $(tooldir)/lib${MULTISUBDIR}; \
|
||||
done
|
||||
@for script in ${SCRIPTS}; do\
|
||||
$(INSTALL_DATA) ${srcdir}/$${script}.ld $(tooldir)/lib${MULTISUBDIR}/$${script}.ld; \
|
||||
done
|
||||
|
||||
info:
|
||||
install-info:
|
||||
clean-info:
|
||||
|
||||
test.o: ${srcdir}/test.c
|
||||
|
||||
# these are for the BSPs
|
||||
crt0.o: ${srcdir}/crt0.S
|
||||
pcrt0.o: ${srcdir}/crt0.S
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) -DGCRT0 ${srcdir}/crt0.S -o ${PCRT0}
|
||||
idtmon.o: ${srcdir}/idtmon.S
|
||||
pmon.o: ${srcdir}/pmon.S
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) $(PART_SPECIFIC_DEFINES) ${srcdir}/pmon.S -o pmon.o
|
||||
vr4300.o: ${srcdir}/vr4300.S
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/vr4300.S
|
||||
vr5xxx.o: ${srcdir}/vr5xxx.S
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/vr5xxx.S
|
||||
lsipmon.o: $(srcdir)/lsipmon.S $(srcdir)/pmon.S
|
||||
jmr3904-io.o: ${srcdir}/jmr3904-io.c
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) -mips3 ${srcdir}/jmr3904-io.c -o $@
|
||||
|
||||
# cma101 can not be compiled mips16, if a mips16 version is needed then
|
||||
# it will have to be built, then this rule can be scrapped, allowing
|
||||
# the implicit rule to run.
|
||||
cma101.o: ${srcdir}/cma101.c
|
||||
$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) -mno-mips16 ${srcdir}/cma101.c
|
||||
|
||||
|
||||
syscalls.o: ${srcdir}/syscalls.c
|
||||
|
||||
# target specific makefile fragment comes in here.
|
||||
@target_makefile_frag@
|
||||
|
||||
Makefile: Makefile.in config.status @host_makefile_frag_path@ @target_makefile_frag_path@
|
||||
$(SHELL) config.status
|
||||
|
||||
config.status: configure
|
||||
$(SHELL) config.status --recheck
|
68
libgloss/mips/array-io.c
Normal file
68
libgloss/mips/array-io.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* array-io.c -- I/O code for the Array Tech RAID disk controller.
|
||||
*
|
||||
* 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 "mips.h"
|
||||
|
||||
/*
|
||||
* outbyte -- shove a byte out the serial port. We wait till the byte
|
||||
*/
|
||||
int
|
||||
outbyte(byte)
|
||||
unsigned char byte;
|
||||
{
|
||||
return (PUTCHAR(byte));
|
||||
}
|
||||
|
||||
/*
|
||||
* inbyte -- get a byte from the serial port
|
||||
*/
|
||||
unsigned char
|
||||
inbyte()
|
||||
{
|
||||
return ((unsigned char)GETCHAR);
|
||||
}
|
||||
|
||||
/*
|
||||
* led_putnum -- print a hex number on the LED. the value of num must be a byte.
|
||||
|
||||
* The max number 15, since the front panel only has 4 LEDs.
|
||||
*/
|
||||
void
|
||||
led_putnum ( num )
|
||||
char num;
|
||||
{
|
||||
print ("Sorry, unimplemented, using putnum instead\r\n");
|
||||
putnum (num);
|
||||
}
|
||||
|
||||
/*
|
||||
* zylons -- draw a rotating pattern. NOTE: this function never returns.
|
||||
*/
|
||||
void
|
||||
zylons()
|
||||
{
|
||||
print ("Sorry, unimplemented\r\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* delay -- a really gross, ugly hack for simple time delays
|
||||
*/
|
||||
void
|
||||
delay (x)
|
||||
int x;
|
||||
{
|
||||
int y = 17;
|
||||
while (x-- !=0)
|
||||
y = y^2;
|
||||
}
|
171
libgloss/mips/array.ld
Normal file
171
libgloss/mips/array.ld
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* memory map assumed by prom and standalone system
|
||||
*
|
||||
* physical kseg1 use
|
||||
*
|
||||
* 0x1fc20000 0xbfc20000
|
||||
* to prom text and read-only data
|
||||
* 0x1fc00000 0xbfc00000 (in cpu board "prom space")
|
||||
*
|
||||
* (Top of RAM - 8K) downward sash and standalone program stack
|
||||
* | ( - 8K to preserve kernel message bufs)
|
||||
* V (standalone programs grow their stack
|
||||
* immediately below sash's stack)
|
||||
*
|
||||
* ^
|
||||
* |
|
||||
* 0x00100000 0xa0100000 upward sash program text, data, and bss
|
||||
*
|
||||
* ^
|
||||
* |
|
||||
* 0x00020000 0xa0020000 upward standalone program text, data, and bss
|
||||
* (kernel is loaded here, also)
|
||||
*
|
||||
* 0x0001ffff 0xa001ffff downward dbgmon stack
|
||||
* |
|
||||
* V
|
||||
*
|
||||
* ^
|
||||
* |
|
||||
* 0x00010000 0xa0010000 upward dbgmon text, data, and bss
|
||||
*
|
||||
* 0x0000ffff 0xa000ffff downward prom monitor stack
|
||||
* |
|
||||
* V
|
||||
*
|
||||
* ^
|
||||
* |
|
||||
* 0x00000500 0xa0000500 upward prom monitor bss
|
||||
*
|
||||
* 0x000004ff 0xa00004ff
|
||||
* to restart block
|
||||
* 0x00000400 0xa0000400
|
||||
*
|
||||
* 0x000003ff 0xa00003ff
|
||||
* to general exception code
|
||||
* 0x00000080 0xa0000080 (note cpu addresses as 0x80000080!)
|
||||
*
|
||||
* 0x0000007f 0xa000007f
|
||||
* to utlbmiss exception code
|
||||
* 0x00000000 0xa0000000 (note cpu addresses as 0x80000000!)
|
||||
*/
|
||||
|
||||
/* Uncomment this if you want srecords.
|
||||
OUTPUT_FORMAT(srec)
|
||||
*/
|
||||
ENTRY(start)
|
||||
STARTUP(crt0.o)
|
||||
INPUT(array.o)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*
|
||||
PROVIDE (__stack = 1M - 8);
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
_gp = ALIGN(16) + 0x8000;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
end = .;
|
||||
_end = .;
|
||||
}
|
300
libgloss/mips/cma101.c
Normal file
300
libgloss/mips/cma101.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* cma101.c -- lo-level support for Cogent CMA101 development 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.
|
||||
*/
|
||||
|
||||
#ifdef __mips16
|
||||
/* The assembler portions of this file need to be re-written to
|
||||
support mips16, if and when that seems useful.
|
||||
*/
|
||||
#error cma101.c can not be compiled -mips16
|
||||
#endif
|
||||
|
||||
|
||||
#include <time.h> /* standard ANSI time routines */
|
||||
|
||||
/* Normally these would appear in a header file for external
|
||||
use. However, we are only building a simple example world at the
|
||||
moment: */
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
#if defined(MIPSEB)
|
||||
#define BYTEREG(b,o) ((volatile unsigned char *)(PHYS_TO_K1((b) + (o) + 7)))
|
||||
#endif /* MIPSEB */
|
||||
#if defined(MIPSEL)
|
||||
#define BYTEREG(b,o) ((volatile unsigned char *)(PHYS_TO_K1((b) + (o))))
|
||||
#endif /* MIPSEL */
|
||||
|
||||
/* I/O addresses: */
|
||||
#define RTCLOCK_BASE (0x0E800000) /* Mk48T02 NVRAM/RTC */
|
||||
#define UART_BASE (0x0E900000) /* NS16C552 DUART */
|
||||
#define LCD_BASE (0x0EB00000) /* Alphanumeric display */
|
||||
|
||||
/* LCD panel manifests: */
|
||||
#define LCD_DATA BYTEREG(LCD_BASE,0)
|
||||
#define LCD_CMD BYTEREG(LCD_BASE,8)
|
||||
|
||||
#define LCD_STAT_BUSY (0x80)
|
||||
#define LCD_SET_DDADDR (0x80)
|
||||
|
||||
/* RTC manifests */
|
||||
/* The lo-offsets are the NVRAM locations (0x7F8 bytes) */
|
||||
#define RTC_CONTROL BYTEREG(RTCLOCK_BASE,0x3FC0)
|
||||
#define RTC_SECS BYTEREG(RTCLOCK_BASE,0x3FC8)
|
||||
#define RTC_MINS BYTEREG(RTCLOCK_BASE,0x3FD0)
|
||||
#define RTC_HOURS BYTEREG(RTCLOCK_BASE,0x3FD8)
|
||||
#define RTC_DAY BYTEREG(RTCLOCK_BASE,0x3FE0)
|
||||
#define RTC_DATE BYTEREG(RTCLOCK_BASE,0x3FE8)
|
||||
#define RTC_MONTH BYTEREG(RTCLOCK_BASE,0x3FF0)
|
||||
#define RTC_YEAR BYTEREG(RTCLOCK_BASE,0x3FF8)
|
||||
|
||||
#define RTC_CTL_LOCK_READ (0x40) /* lock RTC whilst reading */
|
||||
#define RTC_CTL_LOCK_WRITE (0x80) /* lock RTC whilst writing */
|
||||
|
||||
/* Macro to force out-standing memory transfers to complete before
|
||||
next sequence. For the moment we assume that the processor in the
|
||||
CMA101 board supports at least ISA II. */
|
||||
#define DOSYNC() asm(" .set mips2 ; sync ; .set mips0")
|
||||
|
||||
/* We disable interrupts by writing zero to all of the masks, and the
|
||||
global interrupt enable bit: */
|
||||
#define INTDISABLE(sr,tmp) asm("\
|
||||
.set mips2 ; \
|
||||
mfc0 %0,$12 ; \
|
||||
lui %1,0xffff ; \
|
||||
ori %1,%1,0xfffe ; \
|
||||
and %1, %0, %1 ; \
|
||||
mtc0 %1,$12 ; \
|
||||
.set mips0" : "=d" (sr), "=d" (tmp))
|
||||
#define INTRESTORE(sr) asm("\
|
||||
.set mips2 ; \
|
||||
mtc0 %0,$12 ; \
|
||||
.set mips0" : : "d" (sr))
|
||||
|
||||
/* TODO:FIXME: The CPU card support should be in separate source file
|
||||
from the standard CMA101 support provided in this file. */
|
||||
|
||||
/* The CMA101 board being used contains a CMA257 Vr4300 CPU:
|
||||
MasterClock is at 33MHz. PClock is derived from MasterClock by
|
||||
multiplying by the ratio defined by the DivMode pins:
|
||||
DivMode(1:0) MasterClock PClock Ratio
|
||||
00 100MHz 100MHz 1:1
|
||||
01 100MHz 150MHz 1.5:1
|
||||
10 100MHz 200MHz 2:1
|
||||
11 100Mhz 300MHz 3:1
|
||||
|
||||
Are these pins reflected in the EC bits in the CONFIG register? or
|
||||
is that talking about a different clock multiplier?
|
||||
110 = 1
|
||||
111 = 1.5
|
||||
000 = 2
|
||||
001 = 3
|
||||
(all other values are undefined)
|
||||
*/
|
||||
|
||||
#define MASTERCLOCK (33) /* ticks per uS */
|
||||
unsigned int pclock; /* number of PClock ticks per uS */
|
||||
void
|
||||
set_pclock (void)
|
||||
{
|
||||
unsigned int config;
|
||||
asm volatile ("mfc0 %0,$16 ; nop ; nop" : "=r" (config)); /* nasty CP0 register constant */
|
||||
switch ((config >> 28) & 0x7) {
|
||||
case 0x7 : /* 1.5:1 */
|
||||
pclock = (MASTERCLOCK + (MASTERCLOCK / 2));
|
||||
break;
|
||||
|
||||
case 0x0 : /* 2:1 */
|
||||
pclock = (2 * MASTERCLOCK);
|
||||
break;
|
||||
|
||||
case 0x1 : /* 3:1 */
|
||||
pclock = (3 * MASTERCLOCK);
|
||||
break;
|
||||
|
||||
case 0x6 : /* 1:1 */
|
||||
default : /* invalid configuration, so assume the lowest */
|
||||
pclock = MASTERCLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define PCLOCK_WAIT(x) __cpu_timer_poll((x) * pclock)
|
||||
|
||||
/* NOTE: On the Cogent CMA101 board the LCD controller will sometimes
|
||||
return not-busy, even though it is. The work-around is to perform a
|
||||
~50uS delay before checking the busy signal. */
|
||||
|
||||
static int
|
||||
lcd_busy (void)
|
||||
{
|
||||
PCLOCK_WAIT(50); /* 50uS delay */
|
||||
return(*LCD_CMD & LCD_STAT_BUSY);
|
||||
}
|
||||
|
||||
/* Note: This code *ASSUMES* that the LCD has already been initialised
|
||||
by the monitor. It only provides code to write to the LCD, and is
|
||||
not a complete device driver. */
|
||||
|
||||
void
|
||||
lcd_display (int line, const char *msg)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (lcd_busy ())
|
||||
return;
|
||||
|
||||
*LCD_CMD = (LCD_SET_DDADDR | (line == 1 ? 0x40 : 0x00));
|
||||
|
||||
for (n = 0; n < 16; n++) {
|
||||
if (lcd_busy ())
|
||||
return;
|
||||
if (*msg)
|
||||
*LCD_DATA = *msg++;
|
||||
else
|
||||
*LCD_DATA = ' ';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define SM_PATTERN (0x55AA55AA)
|
||||
#define SM_INCR ((256 << 10) / sizeof(unsigned int)) /* 64K words */
|
||||
|
||||
extern unsigned int __buserr_count(void);
|
||||
extern void __default_buserr_handler(void);
|
||||
extern void __restore_buserr_handler(void);
|
||||
|
||||
unsigned int
|
||||
__sizemem ()
|
||||
{
|
||||
volatile unsigned int *base;
|
||||
volatile unsigned int *probe;
|
||||
unsigned int baseorig;
|
||||
unsigned int sr;
|
||||
extern void *end;
|
||||
int extra;
|
||||
|
||||
INTDISABLE(sr,baseorig); /* disable all interrupt masks */
|
||||
|
||||
__default_buserr_handler();
|
||||
__cpu_flush();
|
||||
|
||||
DOSYNC();
|
||||
|
||||
/* _end is the end of the user program. _end may not be properly aligned
|
||||
for an int pointer, so we adjust the address to make sure it is safe.
|
||||
We use void * arithmetic to avoid accidentally truncating the pointer. */
|
||||
|
||||
extra = ((int) &end & (sizeof (int) - 1));
|
||||
base = ((void *) &end + sizeof (int) - extra);
|
||||
baseorig = *base;
|
||||
|
||||
*base = SM_PATTERN;
|
||||
/* This assumes that the instructions fetched between the store, and
|
||||
the following read will have changed the data bus contents: */
|
||||
if (*base == SM_PATTERN) {
|
||||
probe = base;
|
||||
for (;;) {
|
||||
unsigned int probeorig;
|
||||
probe += SM_INCR;
|
||||
probeorig = *probe;
|
||||
/* Check if a bus error occurred: */
|
||||
if (!__buserr_count()) {
|
||||
*probe = SM_PATTERN;
|
||||
DOSYNC();
|
||||
if (*probe == SM_PATTERN) {
|
||||
*probe = ~SM_PATTERN;
|
||||
DOSYNC();
|
||||
if (*probe == ~SM_PATTERN) {
|
||||
if (*base == SM_PATTERN) {
|
||||
*probe = probeorig;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*probe = probeorig;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*base = baseorig;
|
||||
__restore_buserr_handler();
|
||||
__cpu_flush();
|
||||
|
||||
DOSYNC();
|
||||
|
||||
INTRESTORE(sr); /* restore interrupt mask to entry state */
|
||||
|
||||
return((probe - base) * sizeof(unsigned int));
|
||||
}
|
||||
|
||||
/* Provided as a function, so as to avoid reading the I/O location
|
||||
multiple times: */
|
||||
static int
|
||||
convertbcd(byte)
|
||||
unsigned char byte;
|
||||
{
|
||||
return ((((byte >> 4) & 0xF) * 10) + (byte & 0xF));
|
||||
}
|
||||
|
||||
time_t
|
||||
time (_timer)
|
||||
time_t *_timer;
|
||||
{
|
||||
time_t result = 0;
|
||||
struct tm tm;
|
||||
*RTC_CONTROL |= RTC_CTL_LOCK_READ;
|
||||
DOSYNC();
|
||||
|
||||
tm.tm_sec = convertbcd(*RTC_SECS);
|
||||
tm.tm_min = convertbcd(*RTC_MINS);
|
||||
tm.tm_hour = convertbcd(*RTC_HOURS);
|
||||
tm.tm_mday = convertbcd(*RTC_DATE);
|
||||
tm.tm_mon = convertbcd(*RTC_MONTH);
|
||||
tm.tm_year = convertbcd(*RTC_YEAR);
|
||||
|
||||
DOSYNC();
|
||||
*RTC_CONTROL &= ~(RTC_CTL_LOCK_READ | RTC_CTL_LOCK_WRITE);
|
||||
|
||||
tm.tm_isdst = 0;
|
||||
|
||||
/* Check for invalid time information */
|
||||
if ((tm.tm_sec < 60) && (tm.tm_min < 60) && (tm.tm_hour < 24)
|
||||
&& (tm.tm_mday < 32) && (tm.tm_mon < 13)) {
|
||||
|
||||
/* Get the correct year number, but keep it in YEAR-1900 form: */
|
||||
if (tm.tm_year < 70)
|
||||
tm.tm_year += 100;
|
||||
|
||||
#if 0 /* NOTE: mon_printf() can only accept 4 arguments (format string + 3 fields) */
|
||||
mon_printf("[DBG: s=%d m=%d h=%d]", tm.tm_sec, tm.tm_min, tm.tm_hour);
|
||||
mon_printf("[DBG: d=%d m=%d y=%d]", tm.tm_mday, tm.tm_mon, tm.tm_year);
|
||||
#endif
|
||||
|
||||
/* Convert the time-structure into a second count */
|
||||
result = mktime (&tm);
|
||||
}
|
||||
|
||||
if (_timer != NULL)
|
||||
*_timer = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*> EOF cma101.c <*/
|
1254
libgloss/mips/configure
vendored
Executable file
1254
libgloss/mips/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
144
libgloss/mips/configure.in
Normal file
144
libgloss/mips/configure.in
Normal file
@ -0,0 +1,144 @@
|
||||
# Copyright (c) 1995, 1996, 1997, 1998, 1999 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.
|
||||
#
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
AC_PREREQ(2.5)dnl
|
||||
AC_INIT(crt0.S)
|
||||
|
||||
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="${srcdir}/${with_multisrctop}../../.."
|
||||
else
|
||||
libgloss_topdir="${srcdir}/${with_multisrctop}../.."
|
||||
fi
|
||||
else
|
||||
libgloss_topdir="${srcdir}/../.."
|
||||
fi
|
||||
AC_CONFIG_AUX_DIR($libgloss_topdir)
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_ARG_PROGRAM
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# 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 building a library that must be included in all links, so we
|
||||
# can't link an executable until this lib is built.
|
||||
# autoconf should provide a way to do this.
|
||||
|
||||
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
|
||||
|
||||
crt0=crt0.o
|
||||
pcrt0=pcrt0.o
|
||||
|
||||
case "${target}" in
|
||||
mips*-tx39*-*|mipstx39*-*-*)
|
||||
part_specific_obj=
|
||||
part_specific_defines=
|
||||
script_list="dve idt jmr3904app jmr3904dram jmr3904dram-java jmr3904app-java"
|
||||
bsp_list="libdve.a libidt.a libjmr3904.a"
|
||||
;;
|
||||
mips*-lsi*-*)
|
||||
part_specific_obj=entry.o
|
||||
part_specific_defines=
|
||||
script_list="lsi"
|
||||
bsp_list=liblsi.a
|
||||
;;
|
||||
mips64vr5*-*-*)
|
||||
part_specific_obj="vr5xxx.o cma101.o"
|
||||
part_specific_defines=-DR5000
|
||||
script_list="idt pmon ddb lsi idtecoff nullmon"
|
||||
bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
|
||||
;;
|
||||
*)
|
||||
part_specific_obj="vr4300.o cma101.o"
|
||||
part_specific_defines=
|
||||
script_list="idt pmon ddb lsi idtecoff nullmon"
|
||||
bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
|
||||
;;
|
||||
esac
|
||||
|
||||
host_makefile_frag=${srcdir}/../config/default.mh
|
||||
target_makefile_frag=${srcdir}/../config/mips.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(part_specific_obj)
|
||||
AC_SUBST(part_specific_defines)
|
||||
AC_SUBST(script_list)
|
||||
AC_SUBST(bsp_list)
|
||||
AC_SUBST(crt0)
|
||||
AC_SUBST(pcrt0)
|
||||
|
||||
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}
|
||||
)
|
||||
|
||||
|
230
libgloss/mips/crt0.S
Normal file
230
libgloss/mips/crt0.S
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* crt0.S -- startup file for MIPS.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
/*
|
||||
* Set up some room for a stack. We just grab a chunk of memory.
|
||||
*/
|
||||
#define STACK_SIZE 0x4000
|
||||
#define GLOBAL_SIZE 0x2000
|
||||
|
||||
#define STARTUP_STACK_SIZE 0x0100
|
||||
|
||||
/* This is for referencing addresses that are not in the .sdata or
|
||||
.sbss section under embedded-pic, or before we've set up gp. */
|
||||
#ifdef __mips_embedded_pic
|
||||
# ifdef __mips64
|
||||
# define LA(t,x) la t,x-PICBASE ; daddu t,s0,t
|
||||
# else
|
||||
# define LA(t,x) la t,x-PICBASE ; addu t,s0,t
|
||||
# endif
|
||||
#else /* __mips_embedded_pic */
|
||||
# define LA(t,x) la t,x
|
||||
#endif /* __mips_embedded_pic */
|
||||
|
||||
.comm __memsize, 12
|
||||
.comm __lstack, STARTUP_STACK_SIZE
|
||||
.comm __stackbase,4
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
/* Without the following nop, GDB thinks _start is a data variable.
|
||||
* This is probably a bug in GDB in handling a symbol that is at the
|
||||
* start of the .text section.
|
||||
*/
|
||||
nop
|
||||
|
||||
.globl _start
|
||||
.ent _start
|
||||
_start:
|
||||
.set noreorder
|
||||
#ifdef __mips_embedded_pic
|
||||
PICBASE = .+8
|
||||
bal PICBASE
|
||||
nop
|
||||
move s0,$31
|
||||
#endif
|
||||
#if __mips < 3
|
||||
#define STATUS_MASK (SR_CU1|SR_PE)
|
||||
#else
|
||||
# For mips3 or mips4, turn on 64-bit addressing and additional float regs
|
||||
#define STATUS_MASK (SR_CU1|SR_PE|SR_FR|SR_KX|SR_SX|SR_UX)
|
||||
#endif
|
||||
li v0, STATUS_MASK
|
||||
mtc0 v0, C0_SR
|
||||
mtc0 zero, C0_CAUSE
|
||||
nop
|
||||
|
||||
/* Check for FPU presence. Don't check if we know that soft_float is
|
||||
being used. (This also avoids illegal instruction exceptions.) */
|
||||
|
||||
#ifndef __mips_soft_float
|
||||
li t2,0xAAAA5555
|
||||
mtc1 t2,fp0 /* write to FPR 0 */
|
||||
mtc1 zero,fp1 /* write to FPR 1 */
|
||||
mfc1 t0,fp0
|
||||
mfc1 t1,fp1
|
||||
nop
|
||||
bne t0,t2,1f /* check for match */
|
||||
nop
|
||||
bne t1,zero,1f /* double check */
|
||||
nop
|
||||
j 2f /* FPU is present. */
|
||||
nop
|
||||
#endif
|
||||
1:
|
||||
/* FPU is not present. Set status register to say that. */
|
||||
li v0, (STATUS_MASK-(STATUS_MASK & SR_CU1))
|
||||
mtc0 v0, C0_SR
|
||||
nop
|
||||
2:
|
||||
|
||||
|
||||
/* Fix high bits, if any, of the PC so that exception handling
|
||||
doesn't get confused. */
|
||||
LA (v0, 3f)
|
||||
jr v0
|
||||
nop
|
||||
3:
|
||||
LA (gp, _gp) # set the global data pointer
|
||||
.end _start
|
||||
|
||||
/*
|
||||
* zero out the bss section.
|
||||
*/
|
||||
.globl __memsize
|
||||
.globl get_mem_info .text
|
||||
.globl __stack
|
||||
.globl __global
|
||||
.globl zerobss
|
||||
.ent zerobss
|
||||
zerobss:
|
||||
LA (v0, _fbss)
|
||||
LA (v1, _end)
|
||||
3:
|
||||
sw zero,0(v0)
|
||||
bltu v0,v1,3b
|
||||
addiu v0,v0,4 # executed in delay slot
|
||||
|
||||
la t0, __lstack # make a small stack so we
|
||||
addiu sp, t0, STARTUP_STACK_SIZE # can run some C code
|
||||
la a0, __memsize # get the usable memory size
|
||||
jal get_mem_info
|
||||
nop
|
||||
|
||||
/* setup the stack pointer */
|
||||
LA (t0, __stack) # is __stack set ?
|
||||
bne t0,zero,4f
|
||||
nop
|
||||
|
||||
/* NOTE: a0[0] contains the amount of memory available, and
|
||||
not the last memory address. */
|
||||
lw t0,0(a0) # last address of memory available
|
||||
la t1,K0BASE # cached kernel memory
|
||||
addu t0,t0,t1 # get the end of memory address
|
||||
/* We must subtract 24 bytes for the 3 8 byte arguments to main, in
|
||||
case main wants to write them back to the stack. The caller is
|
||||
supposed to allocate stack space for parameters in registers in
|
||||
the old MIPS ABIs. We must do this even though we aren't passing
|
||||
arguments, because main might be declared to have them.
|
||||
|
||||
Some ports need a larger alignment for the stack, so we subtract
|
||||
32, which satisifes the stack for the arguments and keeps the
|
||||
stack pointer better aligned. */
|
||||
subu t0,t0,32 # and generate a starting stack-pointer
|
||||
4:
|
||||
move sp,t0 # set stack pointer
|
||||
sw sp,__stackbase # keep this for future ref
|
||||
.end zerobss
|
||||
|
||||
/*
|
||||
* initialize target specific stuff. Only execute these
|
||||
* functions it they exist.
|
||||
*/
|
||||
.globl hardware_init_hook .text
|
||||
.globl software_init_hook .text
|
||||
.globl __do_global_dtors .text
|
||||
.globl atexit .text
|
||||
.globl exit .text
|
||||
.globl init
|
||||
.ent init
|
||||
init:
|
||||
LA (t9, hardware_init_hook) # init the hardware if needed
|
||||
beq t9,zero,6f
|
||||
nop
|
||||
jal t9
|
||||
nop
|
||||
6:
|
||||
LA (t9, software_init_hook) # init the hardware if needed
|
||||
beq t9,zero,7f
|
||||
nop
|
||||
jal t9
|
||||
nop
|
||||
7:
|
||||
LA (a0, __do_global_dtors)
|
||||
jal atexit
|
||||
nop
|
||||
|
||||
#ifdef GCRT0
|
||||
.globl _ftext
|
||||
.globl _extext
|
||||
LA (a0, _ftext)
|
||||
LA (a1, _etext)
|
||||
jal monstartup
|
||||
nop
|
||||
#endif
|
||||
|
||||
move a0,zero # set argc to 0
|
||||
jal main # call the program start function
|
||||
nop
|
||||
|
||||
# fall through to the "exit" routine
|
||||
jal exit # call libc exit to run the G++
|
||||
# destructors
|
||||
move a0,v0 # pass through the exit code
|
||||
.end init
|
||||
|
||||
/*
|
||||
* _exit -- Exit from the application. Normally we cause a user trap
|
||||
* to return to the ROM monitor for another run. NOTE: This is
|
||||
* the only other routine we provide in the crt0.o object, since
|
||||
* it may be tied to the "_start" routine. It also allows
|
||||
* executables that contain a complete world to be linked with
|
||||
* just the crt0.o object.
|
||||
*/
|
||||
.globl _exit
|
||||
.ent _exit
|
||||
_exit:
|
||||
7:
|
||||
#ifdef GCRT0
|
||||
jal _mcleanup
|
||||
nop
|
||||
#endif
|
||||
# break instruction can cope with 0xfffff, but GAS limits the range:
|
||||
break 1023
|
||||
nop
|
||||
b 7b # but loop back just in-case
|
||||
nop
|
||||
.end _exit
|
||||
|
||||
/* EOF crt0.S */
|
154
libgloss/mips/ddb.ld
Normal file
154
libgloss/mips/ddb.ld
Normal file
@ -0,0 +1,154 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -lpmon -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0100000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
25
libgloss/mips/dtor.C
Normal file
25
libgloss/mips/dtor.C
Normal file
@ -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);
|
||||
}
|
155
libgloss/mips/dve.ld
Normal file
155
libgloss/mips/dve.ld
Normal file
@ -0,0 +1,155 @@
|
||||
/* Linker script for Densan DVE-R3900/20A board */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:3000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -ldve -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0040000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
83
libgloss/mips/dvemon.c
Normal file
83
libgloss/mips/dvemon.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* dve.c -- I/O code for the Densan DVE-R3900 board.
|
||||
*
|
||||
* Copyright (c) 1998, 1999 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.
|
||||
*/
|
||||
|
||||
/* Flag indicating that we are being debugged by GDB. If set,
|
||||
preceded each character output to the console with a ^O,
|
||||
so that GDB will print it instead of discarding it. */
|
||||
|
||||
int output_debug = 1;
|
||||
|
||||
/* Monitor "ci" function (console input) */
|
||||
|
||||
typedef int (*cifunc)(int waitflag);
|
||||
#ifdef __mips64
|
||||
static cifunc ci = (cifunc) 0xffffffffbfc00010L;
|
||||
#else
|
||||
static cifunc ci = (cifunc) 0xbfc00010;
|
||||
#endif
|
||||
|
||||
#define WAIT 1
|
||||
#define NOWAIT 0
|
||||
#define NOCHAR (-1)
|
||||
|
||||
/* Monitor "co" function (console output) */
|
||||
|
||||
typedef void (*cofunc)(int c);
|
||||
#ifdef __mips64
|
||||
static cofunc co = (cofunc) 0xffffffffbfc00018L;
|
||||
#else
|
||||
static cofunc co = (cofunc) 0xbfc00018;
|
||||
#endif
|
||||
|
||||
/* outbyte -- shove a byte out the serial port; used by write.c. */
|
||||
|
||||
int
|
||||
outbyte(byte)
|
||||
unsigned char byte;
|
||||
{
|
||||
/* Output a ^O prefix so that GDB won't discard the output. */
|
||||
if (output_debug)
|
||||
co (0x0f);
|
||||
|
||||
co (byte);
|
||||
return byte;
|
||||
}
|
||||
|
||||
/* inbyte -- get a byte from the serial port; used by read.c. */
|
||||
|
||||
unsigned char
|
||||
inbyte()
|
||||
{
|
||||
return (unsigned char) ci (WAIT);
|
||||
}
|
||||
|
||||
|
||||
/* Structure filled in by get_mem_info. Only the size field is
|
||||
actually used (by sbrk), so the others aren't even filled in. */
|
||||
|
||||
struct s_mem
|
||||
{
|
||||
unsigned int size;
|
||||
unsigned int icsize;
|
||||
unsigned int dcsize;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
get_mem_info (mem)
|
||||
struct s_mem *mem;
|
||||
{
|
||||
mem->size = 0x1000000; /* DVE-R3900 board has 16 MB of RAM */
|
||||
}
|
281
libgloss/mips/entry.S
Normal file
281
libgloss/mips/entry.S
Normal file
@ -0,0 +1,281 @@
|
||||
/* entry.S - exception handler for emulating MIPS16 'entry' and 'exit'
|
||||
pseudo-instructions. These instructions are generated by the compiler
|
||||
when the -mentry switch is used. The instructions are not implemented
|
||||
in the MIPS16 CPU; hence the exception handler that emulates them.
|
||||
|
||||
This module contains the following public functions:
|
||||
|
||||
* void __install_entry_handler(void);
|
||||
|
||||
This function installs the entry/exit exception handler. It should
|
||||
be called before executing any MIPS16 functions that were compiled with
|
||||
-mentry, typically before main() is called.
|
||||
|
||||
* void __remove_entry_handler(void);
|
||||
|
||||
This function removes the entry/exit exception handler. It should
|
||||
be called when the program is exiting, or when it is known that no
|
||||
more MIPS16 functions compiled with -mentry will be called.
|
||||
*/
|
||||
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
#define CAUSE_EXCMASK 0x3c /* mask for ExcCode in Cause Register */
|
||||
#define EXC_RI 0x28 /* 101000 == 10 << 2 */
|
||||
|
||||
/* Set DEBUG to 1 to enable recording of the last 16 interrupt causes. */
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if DEBUG
|
||||
|
||||
.sdata
|
||||
int_count:
|
||||
.space 4 /* interrupt count modulo 16 */
|
||||
int_cause:
|
||||
.space 4*16 /* last 16 interrupt causes */
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.set noreorder /* Do NOT reorder instructions */
|
||||
|
||||
|
||||
/* __entry_exit_handler - the reserved instruction exception handler
|
||||
that emulates the entry and exit instruction. */
|
||||
|
||||
__entry_exit_handler:
|
||||
.set noat /* Do NOT use at register */
|
||||
#if DEBUG
|
||||
/* Must avoid using 'la' pseudo-op because it uses gp register, which
|
||||
may not have a good value in an exception handler. */
|
||||
|
||||
# la k0, int_count /* intcount = (intcount + 1) & 0xf */
|
||||
lui k0 ,%hi(int_count)
|
||||
addiu k0, k0 ,%lo(int_count)
|
||||
lw k1, (k0)
|
||||
addiu k1, k1, 1
|
||||
andi k1, k1, 0x0f
|
||||
sw k1, (k0)
|
||||
# la k0, int_cause /* k1 = &int_cause[intcount] */
|
||||
lui k0, %hi(int_cause)
|
||||
addiu k0, k0, %lo(int_cause)
|
||||
sll k1, k1, 2
|
||||
add k1, k1, k0
|
||||
#endif
|
||||
mfc0 k0, C0_CAUSE /* Fetch cause */
|
||||
#if DEBUG
|
||||
sw k0, -4(k1) /* Save exception cause in buffer */
|
||||
#endif
|
||||
mfc0 k1, C0_EPC /* Check for Reserved Inst. without */
|
||||
and k0, CAUSE_EXCMASK /* destroying any register */
|
||||
subu k0, EXC_RI
|
||||
bne k0, zero, check_others /* Sorry, go do something else */
|
||||
|
||||
and k0, k1, 1 /* Check for TR mode (pc.0 = 1) */
|
||||
beq k0, zero, ri_in_32 /* Sorry, RI in 32-bit mode */
|
||||
xor k1, 1
|
||||
|
||||
/* Since we now are going to emulate or die, we can use all the T-registers */
|
||||
/* that MIPS16 does not use (at, t0-t8), and we don't have to save them. */
|
||||
|
||||
.set at /* Now it's ok to use at again */
|
||||
|
||||
#if 0
|
||||
j leave
|
||||
rfe
|
||||
#endif
|
||||
|
||||
lhu t0, 0(k1) /* Fetch the offending instruction */
|
||||
xor t8, k1, 1 /* Prepare t8 for exit */
|
||||
and t1, t0, 0xf81f /* Check for entry/exit opcode */
|
||||
bne t1, 0xe809, other_ri
|
||||
|
||||
deareg: and t1, t0, 0x0700 /* Isolate the three a-bits */
|
||||
srl t1, 6 /* Adjust them so x4 is applied */
|
||||
slt t2, t1, 17 /* See if this is the exit instruction */
|
||||
beqz t2, doexit
|
||||
la t2, savea
|
||||
subu t2, t1
|
||||
jr t2 /* Jump into the instruction table */
|
||||
rfe /* We run the rest in user-mode */
|
||||
|
||||
/* This is the entry instruction! */
|
||||
sw a3, 12(sp) /* 4: a0-a3 saved */
|
||||
sw a2, 8(sp) /* 3: a0-a2 saved */
|
||||
sw a1, 4(sp) /* 2: a0-a1 saved */
|
||||
sw a0, 0(sp) /* 1: a0 saved */
|
||||
savea: /* 0: No arg regs saved */
|
||||
|
||||
dera: and t1, t0, 0x0020 /* Isolate the save-ra bit */
|
||||
move t7, sp /* Temporary SP */
|
||||
beq t1, zero, desreg
|
||||
subu sp, 32 /* Default SP adjustment */
|
||||
sw ra, -4(t7)
|
||||
subu t7, 4
|
||||
|
||||
desreg: and t1, t0, 0x00c0 /* Isolate the two s-bits */
|
||||
beq t1, zero, leave
|
||||
subu t1, 0x0040
|
||||
beq t1, zero, leave /* Only one to save... */
|
||||
sw s0, -4(t7) /* Do the first one */
|
||||
sw s1, -8(t7) /* Do the last one */
|
||||
|
||||
leave: jr t8 /* Exit to unmodified EPC */
|
||||
nop /* Urgh - the only nop!! */
|
||||
|
||||
doexf0: mtc1 v0,$f0 /* Copy float value */
|
||||
b doex2
|
||||
|
||||
doexf1: mtc1 v1,$f0 /* Copy double value */
|
||||
mtc1 v0,$f1
|
||||
b doex2
|
||||
|
||||
doexit: slt t2, t1, 21
|
||||
beq t2, zero, doexf0
|
||||
slt t2, t1, 25
|
||||
beq t2, zero, doexf1
|
||||
|
||||
doex2: and t1, t0, 0x0020 /* Isolate ra bit */
|
||||
beq t1, zero, dxsreg /* t1 holds ra-bit */
|
||||
addu t7, sp, 32 /* Temporary SP */
|
||||
lw ra, -4(t7)
|
||||
subu t7, 4
|
||||
|
||||
dxsreg: and t1, t0, 0x00c0 /* Isolate the two s-bits */
|
||||
beq t1, zero, leavex
|
||||
subu t1, 0x0040
|
||||
beq t1, zero, leavex /* Only one to save... */
|
||||
lw s0, -4(t7) /* Do the first one */
|
||||
lw s1, -8(t7) /* Do the last one */
|
||||
|
||||
leavex: jr ra /* Exit to ra */
|
||||
addu sp, 32 /* Clean up stack pointer */
|
||||
|
||||
/* Come here for exceptions we can't handle. */
|
||||
|
||||
ri_in_32:
|
||||
other_ri:
|
||||
check_others: /* call the previous handler */
|
||||
la k0,__previous
|
||||
jr k0
|
||||
nop
|
||||
|
||||
__exception_code:
|
||||
.set noreorder
|
||||
la k0, __entry_exit_handler
|
||||
# lui k0, %hi(exception)
|
||||
# addiu k0, k0, %lo(exception)
|
||||
jr k0
|
||||
nop
|
||||
.set reorder
|
||||
__exception_code_end:
|
||||
|
||||
.data
|
||||
__previous:
|
||||
.space (__exception_code_end - __exception_code)
|
||||
.text
|
||||
|
||||
|
||||
/* void __install_entry_handler(void)
|
||||
|
||||
Install our entry/exit reserved instruction exception handler.
|
||||
*/
|
||||
.ent __install_entry_handler
|
||||
.globl __install_entry_handler
|
||||
__install_entry_handler:
|
||||
.set noreorder
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,baseaddr
|
||||
lui a0,0x8000 /* delay slot */
|
||||
lui a0,0xbfc0
|
||||
addiu a0,a0,0x0100
|
||||
baseaddr:
|
||||
addiu a0,a0,0x080 /* a0 = base vector table address */
|
||||
li a1,(__exception_code_end - __exception_code)
|
||||
la a2,__exception_code
|
||||
la a3,__previous
|
||||
/* there must be a better way of doing this???? */
|
||||
copyloop:
|
||||
lw v0,0(a0)
|
||||
sw v0,0(a3)
|
||||
lw v0,0(a2)
|
||||
sw v0,0(a0)
|
||||
addiu a0,a0,4
|
||||
addiu a2,a2,4
|
||||
addiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,copyloop
|
||||
nop
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __install_entry_handler
|
||||
|
||||
|
||||
/* void __remove_entry_handler(void);
|
||||
|
||||
Remove our entry/exit reserved instruction exception handler.
|
||||
*/
|
||||
|
||||
.ent __remove_entry_handler
|
||||
.globl __remove_entry_handler
|
||||
__remove_entry_handler:
|
||||
.set noreorder
|
||||
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,res_baseaddr
|
||||
lui a0,0x8000 /* delay slot */
|
||||
lui a0,0xbfc0
|
||||
addiu a0,a0,0x0200
|
||||
res_baseaddr:
|
||||
addiu a0,a0,0x0180 /* a0 = base vector table address */
|
||||
li a1,(__exception_code_end - __exception_code)
|
||||
la a3,__previous
|
||||
|
||||
/* there must be a better way of doing this???? */
|
||||
res_copyloop:
|
||||
lw v0,0(a3)
|
||||
sw v0,0(a0)
|
||||
addiu a0,a0,4
|
||||
addiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,res_copyloop
|
||||
nop
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __remove_entry_handler
|
||||
|
||||
|
||||
/* software_init_hook - install entry/exit handler and arrange to have it
|
||||
removed at exit. This function is called by crt0.S. */
|
||||
|
||||
.text
|
||||
.globl software_init_hook
|
||||
.ent software_init_hook
|
||||
software_init_hook:
|
||||
.set noreorder
|
||||
subu sp, sp, 8 /* allocate stack space */
|
||||
sw ra, 4(sp) /* save return address */
|
||||
jal __install_entry_handler /* install entry/exit handler */
|
||||
nop
|
||||
lui a0, %hi(__remove_entry_handler) /* arrange for exit to */
|
||||
jal atexit /* de-install handler */
|
||||
addiu a0, a0, %lo(__remove_entry_handler) /* delay slot */
|
||||
lw ra, 4(sp) /* get return address */
|
||||
j ra /* return */
|
||||
addu sp, sp, 8 /* deallocate stack */
|
||||
.set reorder
|
||||
.end software_init_hook
|
155
libgloss/mips/idt.ld
Normal file
155
libgloss/mips/idt.ld
Normal file
@ -0,0 +1,155 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. i.e. the NEC VR4300 (IDT) first free address is actually
|
||||
0xa001af20. */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -lidt -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
93
libgloss/mips/idtecoff.ld
Normal file
93
libgloss/mips/idtecoff.ld
Normal file
@ -0,0 +1,93 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. i.e. the NEC VR4300 (IDT) first free address is actually
|
||||
0xa001af20. */
|
||||
|
||||
ENTRY(_start)
|
||||
STARTUP(crt0.o)
|
||||
OUTPUT_ARCH("mips:4000")
|
||||
OUTPUT_FORMAT("ecoff-bigmips", "ecoff-bigmips", "ecoff-littlemips")
|
||||
GROUP(-lc -lidt -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
. = .;
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
end = .;
|
||||
_end = .;
|
||||
}
|
46
libgloss/mips/idtmon.S
Normal file
46
libgloss/mips/idtmon.S
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* idtmon.S -- lo-level entry points into IDT monitor.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
/* Provide named functions for entry into the IDT monitor: */
|
||||
#define INDIRECT(name,index) \
|
||||
.globl name; \
|
||||
.ent name; \
|
||||
name: la $2,+(0xbfc00000+((index)*8)); \
|
||||
j $2; \
|
||||
.end name
|
||||
|
||||
/* The following magic numbers are for the slots into the IDT monitor: */
|
||||
INDIRECT(open,6)
|
||||
INDIRECT(read,7)
|
||||
INDIRECT(write,8)
|
||||
INDIRECT(close,10)
|
||||
INDIRECT(inbyte,11)
|
||||
INDIRECT(outbyte,12)
|
||||
INDIRECT(mon_printf,16)
|
||||
INDIRECT(_flush_cache,28)
|
||||
INDIRECT(get_mem_info,55) /* expects pointer to three word vector */
|
||||
|
||||
/* EOF idtmon.S */
|
104
libgloss/mips/jmr3904-io.c
Normal file
104
libgloss/mips/jmr3904-io.c
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
|
||||
#define READ_UINT8( _register_, _value_ ) \
|
||||
((_value_) = *((volatile unsigned char *)(_register_)))
|
||||
|
||||
#define WRITE_UINT8( _register_, _value_ ) \
|
||||
(*((volatile unsigned char *)(_register_)) = (_value_))
|
||||
|
||||
/* - Board specific addresses for serial chip */
|
||||
#define DIAG_BASE 0xfffff300
|
||||
#define DIAG_SLCR (DIAG_BASE+0x00)
|
||||
#define DIAG_SLSR (DIAG_BASE+0x04)
|
||||
#define DIAG_SLDICR (DIAG_BASE+0x08)
|
||||
#define DIAG_SLDISR (DIAG_BASE+0x0C)
|
||||
#define DIAG_SFCR (DIAG_BASE+0x10)
|
||||
#define DIAG_SBRG (DIAG_BASE+0x14)
|
||||
#define DIAG_TFIFO (DIAG_BASE+0x20)
|
||||
#define DIAG_RFIFO (DIAG_BASE+0x30)
|
||||
|
||||
#define BRG_T0 0x0000
|
||||
#define BRG_T2 0x0100
|
||||
#define BRG_T4 0x0200
|
||||
#define BRG_T5 0x0300
|
||||
|
||||
|
||||
#define READ_UINT16( _register_, _value_ ) \
|
||||
((_value_) = *((volatile unsigned short *)(_register_)))
|
||||
|
||||
#define WRITE_UINT16( _register_, _value_ ) \
|
||||
(*((volatile unsigned short *)(_register_)) = (_value_))
|
||||
|
||||
unsigned char
|
||||
inbyte (void)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned short disr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
READ_UINT16 (DIAG_SLDISR, disr);
|
||||
if (disr & 0x0001)
|
||||
break;
|
||||
}
|
||||
disr = disr & ~0x0001;
|
||||
READ_UINT8 (DIAG_RFIFO, c);
|
||||
WRITE_UINT16 (DIAG_SLDISR, disr);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
outbyte (unsigned char c)
|
||||
{
|
||||
unsigned short disr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
READ_UINT16 (DIAG_SLDISR, disr);
|
||||
if (disr & 0x0002)
|
||||
break;
|
||||
}
|
||||
disr = disr & ~0x0002;
|
||||
WRITE_UINT8 (DIAG_TFIFO, c);
|
||||
WRITE_UINT16 (DIAG_SLDISR, disr);
|
||||
}
|
||||
|
||||
/* Stuff required to setup IO on this board */
|
||||
void board_serial_init (void)
|
||||
{
|
||||
WRITE_UINT16 (DIAG_SLCR, 0x0020);
|
||||
WRITE_UINT16 (DIAG_SLDICR, 0x0000);
|
||||
WRITE_UINT16 (DIAG_SFCR, 0x0000);
|
||||
WRITE_UINT16 (DIAG_SBRG, BRG_T2 | 5);
|
||||
}
|
||||
|
||||
/* If you want this to be initialized as part of the stuff which gets called
|
||||
by crt0, it should be named 'hardware_init_hook'.
|
||||
Local implementations may want to move or add to this function OR
|
||||
do the initializations after main() is entered.
|
||||
*/
|
||||
void hardware_init_hook(void)
|
||||
{
|
||||
board_serial_init() ;
|
||||
}
|
||||
|
||||
/* Structure filled in by get_mem_info. Only the size field is
|
||||
actually used (by sbrk), so the others aren't even filled in. */
|
||||
|
||||
struct s_mem
|
||||
{
|
||||
unsigned int size;
|
||||
unsigned int icsize;
|
||||
unsigned int dcsize;
|
||||
};
|
||||
|
||||
/* mem_size is provided in the linker script so that we don't have to
|
||||
define it here. */
|
||||
extern char _mem_size[];
|
||||
|
||||
void
|
||||
get_mem_info (mem)
|
||||
struct s_mem *mem;
|
||||
{
|
||||
mem->size = (unsigned int)_mem_size;
|
||||
}
|
127
libgloss/mips/jmr3904app-java.ld
Normal file
127
libgloss/mips/jmr3904app-java.ld
Normal file
@ -0,0 +1,127 @@
|
||||
/* Linker script forJMR 3904 board using Java + qthreads */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:3000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -ljmr3904 -lgcc -lgcjcoop)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
PROVIDE (_mem_size = 0x100000); /* JMR3904 comes as standard with 512k of RAM */
|
||||
|
||||
/* Set the size of the stack for Java with qthreads. */
|
||||
PROVIDE (_Jv_QthreadsStackSize = 0x10000);
|
||||
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80008000;
|
||||
/* This is NOT the address which fits with the monitor from jmr. */
|
||||
/* It fits the Cygmon ROMS */
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
. += 0x2000 ; /* 8k bytes of stack. */
|
||||
__stack = ALIGN(64) ;
|
||||
. = __stack ;
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
156
libgloss/mips/jmr3904app.ld
Normal file
156
libgloss/mips/jmr3904app.ld
Normal file
@ -0,0 +1,156 @@
|
||||
/* Linker script forJMR 3904 board */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:3000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -ljmr3904 -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
PROVIDE (_mem_size = 0x100000); /* JMR3904 comes as standard with 512k of RAM */
|
||||
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x80008000;
|
||||
/* This is NOT the address which fits with the monitor from jmr. */
|
||||
/* It fits the Cygmon ROMS */
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
. += 0x2000 ; /* 8k bytes of stack. */
|
||||
__stack = ALIGN(64) ;
|
||||
. = __stack ;
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
130
libgloss/mips/jmr3904dram-java.ld
Normal file
130
libgloss/mips/jmr3904dram-java.ld
Normal file
@ -0,0 +1,130 @@
|
||||
/* Linker script forJMR 3904 board using Java + qthreads */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:3000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -ljmr3904 -lgcc -lgcjcoop)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
PROVIDE (_mem_size = 0x100000); /* JMR3904 comes as standard with 512k of RAM */
|
||||
/* but this is 1 Mb */
|
||||
|
||||
/* Set the size of the stack for Java with qthreads. */
|
||||
PROVIDE (_Jv_QthreadsStackSize = 0x10000);
|
||||
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Load everything into DRAM, except for the stack. Put stack in SRAM */
|
||||
. = 0x88000000;
|
||||
/* This is NOT the address which fits with the monitor from jmr. */
|
||||
/* It fits the Cygmon ROMS */
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
. = .;
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* Put stack in SRAM (8 Kb); this size is the same as the stack from
|
||||
the original script (when everything was in SRAM). */
|
||||
__stack = 0x8000A000;
|
||||
|
||||
/* 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) }
|
||||
}
|
127
libgloss/mips/jmr3904dram.ld
Normal file
127
libgloss/mips/jmr3904dram.ld
Normal file
@ -0,0 +1,127 @@
|
||||
/* Linker script forJMR 3904 board */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:3000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -ljmr3904 -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
PROVIDE (_mem_size = 0x100000); /* JMR3904 comes as standard with 512k of RAM */
|
||||
/* but this is 1 Mb */
|
||||
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Load everything into DRAM, except for the stack. Put stack in SRAM */
|
||||
. = 0x88000000;
|
||||
/* This is NOT the address which fits with the monitor from jmr. */
|
||||
/* It fits the Cygmon ROMS */
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
. = .;
|
||||
.rdata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* Put stack in SRAM (8 Kb); this size is the same as the stack from
|
||||
the original script (when everything was in SRAM). */
|
||||
__stack = 0x8000A000;
|
||||
|
||||
/* 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) }
|
||||
}
|
121
libgloss/mips/lsi.ld
Normal file
121
libgloss/mips/lsi.ld
Normal file
@ -0,0 +1,121 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:4000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -llsi -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
end = .;
|
||||
_end = .;
|
||||
}
|
595
libgloss/mips/lsi33k-stub.c
Normal file
595
libgloss/mips/lsi33k-stub.c
Normal file
@ -0,0 +1,595 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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>
|
||||
#include "dbgmon.h"
|
||||
#include "parser.h"
|
||||
#include "ctype.h"
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* external low-level support routines
|
||||
*/
|
||||
|
||||
extern putchar(); /* write a single character */
|
||||
extern getchar(); /* read and return a single char */
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Stuff for stdio-like gets_debugger_check() */
|
||||
|
||||
#define CTRL(x) ('x'&0x1f)
|
||||
#define DEL 0x7f
|
||||
#define INTR CTRL(C)
|
||||
#define BELL 0x7
|
||||
#define PROMPT "? "
|
||||
|
||||
#define BUFSIZE 512 /* Big enough for register packets */
|
||||
|
||||
static int initialized = 0; /* !0 means we've been initialized */
|
||||
|
||||
static char hexchars[]="0123456789abcdef";
|
||||
|
||||
extern unsigned int _regs[]; /* Saved registers from client */
|
||||
|
||||
/* 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;
|
||||
|
||||
/* At this point, the start character ($) has been received through
|
||||
* the debug monitor parser. Get the remaining characters and
|
||||
* process them.
|
||||
*/
|
||||
|
||||
checksum = 0;
|
||||
xmitcsum = -1;
|
||||
count = 0;
|
||||
|
||||
/* read until a # or end of buffer is found */
|
||||
|
||||
while (count < BUFSIZE)
|
||||
{
|
||||
ch = getchar();
|
||||
if (ch == '#')
|
||||
break;
|
||||
checksum = checksum + ch;
|
||||
buffer[count] = ch;
|
||||
count = count + 1;
|
||||
}
|
||||
|
||||
if (count >= BUFSIZE)
|
||||
buffer[count] = 0;
|
||||
|
||||
if (ch == '#')
|
||||
{
|
||||
xmitcsum = hex(getchar()) << 4;
|
||||
xmitcsum |= hex(getchar());
|
||||
#if 0
|
||||
/* Humans shouldn't have to figure out checksums to type to it. */
|
||||
putchar ('+');
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (checksum != xmitcsum)
|
||||
{
|
||||
putchar('-'); /* failed checksum */
|
||||
return; /* Back to monitor loop */
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar('+'); /* successful transfer */
|
||||
|
||||
/* if a sequence char is present, reply the sequence ID */
|
||||
|
||||
if (buffer[2] == ':')
|
||||
{
|
||||
putchar(buffer[0]);
|
||||
putchar(buffer[1]);
|
||||
|
||||
/* remove sequence chars from buffer */
|
||||
|
||||
count = strlen(buffer);
|
||||
for (i=3; i <= count; i++)
|
||||
buffer[i-3] = buffer[i];
|
||||
}
|
||||
|
||||
/* Buffer command received- go and process it. */
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* send the packet in buffer. */
|
||||
|
||||
static void
|
||||
putpacket(buffer)
|
||||
unsigned char *buffer;
|
||||
{
|
||||
unsigned char checksum;
|
||||
int count;
|
||||
unsigned char ch;
|
||||
|
||||
/* $<packet info>#<checksum>. */
|
||||
do
|
||||
{
|
||||
putchar('$');
|
||||
checksum = 0;
|
||||
count = 0;
|
||||
|
||||
while (ch = buffer[count])
|
||||
{
|
||||
if (! putchar(ch))
|
||||
return;
|
||||
checksum += ch;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
putchar('#');
|
||||
putchar(hexchars[checksum >> 4]);
|
||||
putchar(hexchars[checksum & 0xf]);
|
||||
|
||||
}
|
||||
while (getchar() != '+');
|
||||
}
|
||||
|
||||
static char remcomInBuffer[BUFSIZE];
|
||||
static char remcomOutBuffer[BUFSIZE];
|
||||
|
||||
/* 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;
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
ch = *mem++;
|
||||
if (mem_err)
|
||||
return 0;
|
||||
*buf++ = hexchars[ch >> 4];
|
||||
*buf++ = hexchars[ch & 0xf];
|
||||
}
|
||||
|
||||
*buf = 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;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
ch = hex(*buf++) << 4;
|
||||
ch |= hex(*buf++);
|
||||
*mem++ = ch;
|
||||
if (mem_err)
|
||||
return 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[] = {
|
||||
{0x06, SIGSEGV}, /* instruction access error */
|
||||
{0x0a, SIGILL}, /* privileged instruction */
|
||||
{0x0a, SIGILL}, /* illegal instruction */
|
||||
{0x0b, SIGEMT}, /* cp disabled */
|
||||
{0x07, SIGSEGV}, /* data access exception */
|
||||
{0x09, SIGTRAP}, /* ta 1 - normal breakpoint instruction */
|
||||
{0, 0} /* Must be last */
|
||||
};
|
||||
|
||||
/* 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 lets GDB know that an exception has occured. */
|
||||
|
||||
static void
|
||||
debug_handle_exception ()
|
||||
{
|
||||
int tt; /* Trap type */
|
||||
int sigval;
|
||||
char *ptr;
|
||||
|
||||
tt = (_regs[R_CAUSE] >> 2) & 0x0f;
|
||||
|
||||
/* 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[R_EPC >> 4];
|
||||
*ptr++ = hexchars[R_EPC & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)&_regs[R_EPC], ptr, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[R_FP >> 4];
|
||||
*ptr++ = hexchars[R_FP & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)&_regs[R_FP], ptr, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = hexchars[R_SP >> 4];
|
||||
*ptr++ = hexchars[R_SP & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = mem2hex((char *)&_regs[R_SP], ptr, 4, 0);
|
||||
*ptr++ = ';';
|
||||
|
||||
*ptr++ = 0;
|
||||
|
||||
putpacket(remcomOutBuffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void process_packet()
|
||||
{
|
||||
|
||||
char *ptr;
|
||||
int length;
|
||||
int addr;
|
||||
int sigval;
|
||||
int tt; /* Trap type */
|
||||
|
||||
remcomOutBuffer[0] = 0;
|
||||
getpacket(remcomInBuffer);
|
||||
switch (remcomInBuffer[0])
|
||||
{
|
||||
|
||||
/* Return Last SIGVAL */
|
||||
|
||||
case '?':
|
||||
tt = (_regs[R_CAUSE] >> 2) & 0x0f;
|
||||
sigval = computeSignal(tt);
|
||||
remcomOutBuffer[0] = 'S';
|
||||
remcomOutBuffer[1] = hexchars[sigval >> 4];
|
||||
remcomOutBuffer[2] = hexchars[sigval & 0xf];
|
||||
remcomOutBuffer[3] = 0;
|
||||
break;
|
||||
|
||||
/* toggle debug flag */
|
||||
|
||||
case 'd':
|
||||
break;
|
||||
|
||||
/* Return the values of the CPU registers */
|
||||
|
||||
case 'g':
|
||||
ptr = remcomOutBuffer;
|
||||
ptr = mem2hex((char *)_regs, ptr, 32 * 4, 0); /* General Purpose Registers */
|
||||
ptr = mem2hex((char *)&_regs[R_EPC], ptr, 9 * 4, 0); /* CP0 Registers */
|
||||
break;
|
||||
|
||||
/* set the value of the CPU registers - return OK */
|
||||
|
||||
case 'G':
|
||||
ptr = &remcomInBuffer[1];
|
||||
hex2mem(ptr, (char *)_regs, 32 * 4, 0); /* General Purpose Registers */
|
||||
hex2mem(ptr + 32 * 4 * 2, (char *)&_regs[R_EPC], 9 * 4, 0); /* CP0 Registers */
|
||||
strcpy(remcomOutBuffer,"OK");
|
||||
break;
|
||||
|
||||
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
|
||||
|
||||
case 'm':
|
||||
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;
|
||||
|
||||
/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
|
||||
|
||||
case 'M':
|
||||
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;
|
||||
|
||||
/* cAA..AA Continue at address AA..AA(optional) */
|
||||
|
||||
case 'c':
|
||||
|
||||
/* try to read optional parameter, pc unchanged if no parm */
|
||||
|
||||
ptr = &remcomInBuffer[1];
|
||||
if (hexToInt(&ptr, &addr))
|
||||
{
|
||||
gdb_go ( addr );
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_cont();
|
||||
}
|
||||
return;
|
||||
|
||||
/* kill the program */
|
||||
|
||||
case 'k':
|
||||
break;
|
||||
|
||||
/* Reset */
|
||||
|
||||
case 'r':
|
||||
break;
|
||||
|
||||
/* switch */
|
||||
|
||||
}
|
||||
|
||||
/* Reply to the request */
|
||||
|
||||
putpacket(remcomOutBuffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gets_debugger_check - This is the same as the stdio gets, but we also
|
||||
* check for a leading $ in the buffer. This so we
|
||||
* gracefully handle the GDB protocol packets.
|
||||
*/
|
||||
|
||||
char *
|
||||
gets_debugger_check(buf)
|
||||
char *buf;
|
||||
{
|
||||
register char c;
|
||||
char *bufp;
|
||||
|
||||
bufp = buf;
|
||||
for (;;)
|
||||
{
|
||||
c = getchar();
|
||||
switch (c)
|
||||
{
|
||||
|
||||
/* quote next char */
|
||||
|
||||
case '$':
|
||||
if ( buf == bufp )
|
||||
process_packet();
|
||||
break;
|
||||
|
||||
case CTRL(V):
|
||||
c = getchar();
|
||||
if (bufp < &buf[LINESIZE-3])
|
||||
{
|
||||
rmw_byte (bufp++,c);
|
||||
showchar(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar(BELL);
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
putchar('\n');
|
||||
rmw_byte (bufp,0);
|
||||
return(buf);
|
||||
|
||||
case CTRL(H):
|
||||
case DEL:
|
||||
if (bufp > buf)
|
||||
{
|
||||
bufp--;
|
||||
putchar(CTRL(H));
|
||||
putchar(' ');
|
||||
putchar(CTRL(H));
|
||||
}
|
||||
break;
|
||||
|
||||
case CTRL(U):
|
||||
if (bufp > buf)
|
||||
{
|
||||
printf("^U\n%s", PROMPT);
|
||||
bufp = buf;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
c = ' ';
|
||||
|
||||
default:
|
||||
/*
|
||||
* Make sure there's room for this character
|
||||
* plus a trailing \n and 0 byte
|
||||
*/
|
||||
if (isprint(c) && bufp < &buf[LINESIZE-3])
|
||||
{
|
||||
rmw_byte ( bufp++, c );
|
||||
putchar(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar(BELL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
179
libgloss/mips/lsi33k-stub.h
Normal file
179
libgloss/mips/lsi33k-stub.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*STARTINC
|
||||
*
|
||||
* COPYRIGHT (C) 1991, 1992 ARRAY TECHNOLOGY CORPORATION
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This software is confidential information which is proprietary to and
|
||||
* a trade secret of ARRAY Technology Corporation. Use, duplication, or
|
||||
* disclosure is subject to the terms of a separate license agreement.
|
||||
*
|
||||
*
|
||||
* NAME:
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
*
|
||||
*ENDINC
|
||||
*/
|
||||
|
||||
/* %Q% %I% %M% */
|
||||
|
||||
/*
|
||||
* Copyright 1985 by MIPS Computer Systems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* dbgmon.h -- debugging monitor definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* catch bogus compiles
|
||||
*/
|
||||
#if defined(MIPSEB) && defined(MIPSEL)
|
||||
# include "error -- both MIPSEB and MIPSEL defined"
|
||||
#endif
|
||||
|
||||
#if !defined(MIPSEB) && !defined(MIPSEL)
|
||||
# include "error -- neither MIPSEB or MIPSEL defined"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PROM_STACK is the address of the first word above the prom stack
|
||||
* the prom stack grows downward from the first word less than PROM_STACK
|
||||
*/
|
||||
#define PROM_STACK 0xa0010000
|
||||
|
||||
/*
|
||||
* register names
|
||||
*/
|
||||
#define R_R0 0
|
||||
#define R_R1 1
|
||||
#define R_R2 2
|
||||
#define R_R3 3
|
||||
#define R_R4 4
|
||||
#define R_R5 5
|
||||
#define R_R6 6
|
||||
#define R_R7 7
|
||||
#define R_R8 8
|
||||
#define R_R9 9
|
||||
#define R_R10 10
|
||||
#define R_R11 11
|
||||
#define R_R12 12
|
||||
#define R_R13 13
|
||||
#define R_R14 14
|
||||
#define R_R15 15
|
||||
#define R_R16 16
|
||||
#define R_R17 17
|
||||
#define R_R18 18
|
||||
#define R_R19 19
|
||||
#define R_R20 20
|
||||
#define R_R21 21
|
||||
#define R_R22 22
|
||||
#define R_R23 23
|
||||
#define R_R24 24
|
||||
#define R_R25 25
|
||||
#define R_R26 26
|
||||
#define R_R27 27
|
||||
#define R_R28 28
|
||||
#define R_R29 29
|
||||
#define R_R30 30
|
||||
#define R_R31 31
|
||||
#define R_F0 32
|
||||
#define R_F1 33
|
||||
#define R_F2 34
|
||||
#define R_F3 35
|
||||
#define R_F4 36
|
||||
#define R_F5 37
|
||||
#define R_F6 38
|
||||
#define R_F7 39
|
||||
#define R_F8 40
|
||||
#define R_F9 41
|
||||
#define R_F10 42
|
||||
#define R_F11 43
|
||||
#define R_F12 44
|
||||
#define R_F13 45
|
||||
#define R_F14 46
|
||||
#define R_F15 47
|
||||
#define R_F16 48
|
||||
#define R_F17 49
|
||||
#define R_F18 50
|
||||
#define R_F19 51
|
||||
#define R_F20 52
|
||||
#define R_F21 53
|
||||
#define R_F22 54
|
||||
#define R_F23 55
|
||||
#define R_F24 56
|
||||
#define R_F25 57
|
||||
#define R_F26 58
|
||||
#define R_F27 59
|
||||
#define R_F28 60
|
||||
#define R_F29 61
|
||||
#define R_F30 62
|
||||
#define R_F31 63
|
||||
#define R_EPC 64
|
||||
#define R_MDHI 65
|
||||
#define R_MDLO 66
|
||||
#define R_SR 67
|
||||
#define R_CAUSE 68
|
||||
#define R_BADVADDR 69
|
||||
#define R_DCIC 70
|
||||
#define R_BPC 71
|
||||
#define R_BDA 72
|
||||
#define R_EXCTYPE 73
|
||||
#define NREGS 74
|
||||
|
||||
/*
|
||||
* compiler defined bindings
|
||||
*/
|
||||
#define R_ZERO R_R0
|
||||
#define R_AT R_R1
|
||||
#define R_V0 R_R2
|
||||
#define R_V1 R_R3
|
||||
#define R_A0 R_R4
|
||||
#define R_A1 R_R5
|
||||
#define R_A2 R_R6
|
||||
#define R_A3 R_R7
|
||||
#define R_T0 R_R8
|
||||
#define R_T1 R_R9
|
||||
#define R_T2 R_R10
|
||||
#define R_T3 R_R11
|
||||
#define R_T4 R_R12
|
||||
#define R_T5 R_R13
|
||||
#define R_T6 R_R14
|
||||
#define R_T7 R_R15
|
||||
#define R_S0 R_R16
|
||||
#define R_S1 R_R17
|
||||
#define R_S2 R_R18
|
||||
#define R_S3 R_R19
|
||||
#define R_S4 R_R20
|
||||
#define R_S5 R_R21
|
||||
#define R_S6 R_R22
|
||||
#define R_S7 R_R23
|
||||
#define R_T8 R_R24
|
||||
#define R_T9 R_R25
|
||||
#define R_K0 R_R26
|
||||
#define R_K1 R_R27
|
||||
#define R_GP R_R28
|
||||
#define R_SP R_R29
|
||||
#define R_FP R_R30
|
||||
#define R_RA R_R31
|
||||
|
||||
/*
|
||||
* memory reference widths
|
||||
*/
|
||||
#define SW_BYTE 1
|
||||
#define SW_HALFWORD 2
|
||||
#define SW_WORD 4
|
||||
|
||||
/*
|
||||
* Monitor modes
|
||||
*/
|
||||
#define MODE_DBGMON 0 /* debug monitor is executing */
|
||||
#define MODE_CLIENT 1 /* client is executing */
|
||||
|
||||
/*
|
||||
* String constants
|
||||
*/
|
||||
#define DEFAULT_STRLEN 70 /* default max strlen for string cmd */
|
||||
|
2
libgloss/mips/lsipmon.S
Normal file
2
libgloss/mips/lsipmon.S
Normal file
@ -0,0 +1,2 @@
|
||||
#define LSI 1
|
||||
#include "pmon.S"
|
69
libgloss/mips/nullmon.c
Normal file
69
libgloss/mips/nullmon.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* nullmon.c - Stub or monitor services.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This is a ROMSTUB
|
||||
Various libraries in libgloss may reference board specific services.
|
||||
These are often performed by system calls and by rom specific
|
||||
interfaces such as dvemon.c This file defines the null interface in
|
||||
which the rom monitor either does not exist or is not used.
|
||||
Linking with this file supports applications which only exercise
|
||||
the processor, specifically, the GDB test suite.
|
||||
By linking this object in rather than a monitor specific support
|
||||
we can insure that the testsuite will run without references or
|
||||
linkages to nonexistent monitor services.
|
||||
Similarly, every service provided by this file muse be provided by all
|
||||
monitor speciifc interfaces.
|
||||
PLEASE DO NOT MAKE THIS FILE SPECIFIC TO ANY MONITOR
|
||||
*/
|
||||
|
||||
/* This form is giving linker relocation errors */
|
||||
#if ! defined(BOARD_MEM_SIZE)
|
||||
#define BOARD_MEM_SIZE 0x100000 /* About a megabyte */
|
||||
#endif
|
||||
extern unsigned char _ftext ; /* Defined in nullmon.ld */
|
||||
extern unsigned char _end ; /* Defined in nullmon.ld */
|
||||
|
||||
#if defined(FIXME_WARNINGS)
|
||||
#warning("FIXME: struct s_mem belongs in a header file")
|
||||
#endif
|
||||
struct s_mem
|
||||
{ unsigned int size;
|
||||
unsigned int icsize;
|
||||
unsigned int dcsize;
|
||||
};
|
||||
|
||||
void
|
||||
get_mem_info (mem)
|
||||
struct s_mem *mem;
|
||||
{ char * t1, * t2 ;
|
||||
unsigned long long tmp ;
|
||||
t1 = & _ftext ;
|
||||
t2 = & _end ;
|
||||
tmp = (unsigned long long) (t2 - t1) ;
|
||||
tmp = (unsigned long long) BOARD_MEM_SIZE - tmp ;
|
||||
mem->size = tmp ;
|
||||
}
|
||||
|
||||
/* SYSTEM INTERFACE
|
||||
Since we are defining a NULL operating environment here, I am
|
||||
entering the stub definitions for the GNUpro libraries, System Calls.
|
||||
I would rather not to even pretend to support these functions but, they
|
||||
get pulled in by other libraries.
|
||||
*/
|
||||
|
||||
int read(int file, char * ptr , int len) { return 0 ; }
|
||||
int close (int file) { return -1 ; }
|
||||
int write(int file , char * ptr, int len) { return 0 ; }
|
||||
/*eof*/
|
156
libgloss/mips/nullmon.ld
Normal file
156
libgloss/mips/nullmon.ld
Normal file
@ -0,0 +1,156 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:4000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -lnullmon -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
. = ALIGN(64) ;
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
|
||||
/* 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) }
|
||||
}
|
177
libgloss/mips/pmon.S
Normal file
177
libgloss/mips/pmon.S
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* pmon.S -- low-level entry points into PMON monitor.
|
||||
*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#if __mips < 3
|
||||
/* This machine does not support 64-bit operations. */
|
||||
#define ADDU addu
|
||||
#define SUBU subu
|
||||
#else
|
||||
/* This machine supports 64-bit operations. */
|
||||
#define ADDU daddu
|
||||
#define SUBU dsubu
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
#ifdef LSI
|
||||
#define PMON_VECTOR 0xffffffffbfc00200
|
||||
#else
|
||||
#define PMON_VECTOR 0xffffffffbfc00500
|
||||
#endif
|
||||
|
||||
#ifndef __mips_eabi
|
||||
/* Provide named functions for entry into the monitor: */
|
||||
#define INDIRECT(name,index) \
|
||||
.globl name; \
|
||||
.ent name; \
|
||||
.set noreorder; \
|
||||
name: la $2,+(PMON_VECTOR+((index)*4)); \
|
||||
lw $2,0($2); \
|
||||
j $2; \
|
||||
nop; \
|
||||
.set reorder; \
|
||||
.end name
|
||||
|
||||
#else
|
||||
#define INDIRECT(name,index) \
|
||||
.globl name; \
|
||||
.ent name; \
|
||||
.set noreorder; \
|
||||
name: la $2,+(PMON_VECTOR+((index)*4)); \
|
||||
lw $2,0($2); \
|
||||
SUBU sp,sp,0x40; \
|
||||
sd ra,0x38(sp); \
|
||||
sd fp,0x30(sp); \
|
||||
jal $2; \
|
||||
move fp,sp; \
|
||||
ld ra,0x38(sp); \
|
||||
ld fp,0x30(sp); \
|
||||
j ra; \
|
||||
ADDU sp,sp,0x40; \
|
||||
.set reorder; \
|
||||
.end name
|
||||
#endif
|
||||
|
||||
|
||||
/* The following magic numbers are for the slots into the PMON monitor */
|
||||
/* The first are used as the lo-level library run-time: */
|
||||
INDIRECT(read,0)
|
||||
INDIRECT(write,1)
|
||||
INDIRECT(open,2)
|
||||
INDIRECT(close,3)
|
||||
/* The following are useful monitor routines: */
|
||||
INDIRECT(mon_ioctl,4)
|
||||
INDIRECT(mon_printf,5)
|
||||
INDIRECT(mon_vsprintf,6)
|
||||
INDIRECT(mon_ttctl,7)
|
||||
INDIRECT(mon_cliexit,8)
|
||||
INDIRECT(mon_getenv,9)
|
||||
INDIRECT(mon_onintr,10)
|
||||
INDIRECT(mon_flush_cache,11)
|
||||
INDIRECT(_flush_cache,11)
|
||||
INDIRECT(mon_exception,12)
|
||||
|
||||
/* The following routine is required by the "print()" function: */
|
||||
.globl outbyte
|
||||
.ent outbyte
|
||||
.set noreorder
|
||||
outbyte:
|
||||
subu sp,sp,0x20 /* allocate stack space for string */
|
||||
sd ra,0x18(sp) /* stack return address */
|
||||
sd fp,0x10(sp) /* stack frame-pointer */
|
||||
move fp,sp /* take a copy of the stack pointer */
|
||||
/* We leave so much space on the stack for the string (16
|
||||
characters), since the call to mon_printf seems to corrupt
|
||||
the 8bytes at offset 8 into the string/stack. */
|
||||
sb a0,0x00(sp) /* character to print */
|
||||
sb z0,0x01(sp) /* NUL terminator */
|
||||
jal mon_printf /* and output the string */
|
||||
move a0,sp /* take a copy of the string pointer {DELAY SLOT} */
|
||||
|
||||
move sp,fp /* recover stack pointer */
|
||||
ld ra,0x18(sp) /* recover return address */
|
||||
ld fp,0x10(sp) /* recover frame-pointer */
|
||||
j ra /* return to the caller */
|
||||
addu sp,sp,0x20 /* dump the stack space {DELAY SLOT} */
|
||||
.set reorder
|
||||
.end outbyte
|
||||
|
||||
/* The following routine is required by the "sbrk()" function: */
|
||||
.globl get_mem_info
|
||||
.ent get_mem_info
|
||||
.set noreorder
|
||||
get_mem_info:
|
||||
# in: a0 = pointer to 3 word structure
|
||||
# out: void
|
||||
subu sp,sp,0x18 /* create some stack space */
|
||||
sd ra,0x00(sp) /* stack return address */
|
||||
sd fp,0x08(sp) /* stack frame-pointer */
|
||||
sd a0,0x10(sp) /* stack structure pointer */
|
||||
move fp,sp /* take a copy of the stack pointer */
|
||||
|
||||
# The monitor has already sized memory, but unfortunately we
|
||||
# do not have access to the data location containing the
|
||||
# memory size.
|
||||
|
||||
jal __sizemem
|
||||
nop
|
||||
|
||||
ld a0,0x10(sp) # recover structure pointer
|
||||
sw v0,0(a0) # amount of memory available
|
||||
|
||||
# Deal with getting the cache size information:
|
||||
mfc0 a1, C0_CONFIG
|
||||
nop
|
||||
nop
|
||||
andi a2,a1,0x7 << 9 # bits 11..9 for instruction cache size
|
||||
sll a2,a2,12 - 8
|
||||
sw a2,4(a0)
|
||||
andi a2,a1,0x7 << 6 # bits 8..6 for data cache size
|
||||
sll a2,a2,12 - 5
|
||||
sw a2,8(a0) # data cache size
|
||||
#
|
||||
move sp,fp /* recover stack pointer */
|
||||
ld ra,0x00(sp) /* recover return address */
|
||||
ld fp,0x08(sp) /* recover frame-pointer */
|
||||
j ra /* return to the caller */
|
||||
addu sp,sp,0x18 /* restore stack pointer {DELAY SLOT} */
|
||||
.set reorder
|
||||
.end get_mem_info
|
||||
|
||||
#ifdef LSI
|
||||
|
||||
# For the LSI MiniRISC board, we can safely assume that we have
|
||||
# at least one megabyte of RAM.
|
||||
|
||||
.globl __sizemem
|
||||
.ent __sizemem
|
||||
__sizemem:
|
||||
li v0,0x100000
|
||||
j ra
|
||||
.end __sizemem
|
||||
#else
|
||||
|
||||
|
||||
#endif
|
||||
/* EOF pmon.S */
|
155
libgloss/mips/pmon.ld
Normal file
155
libgloss/mips/pmon.ld
Normal file
@ -0,0 +1,155 @@
|
||||
/* The following TEXT start address leaves space for the monitor
|
||||
workspace. */
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH("mips:4000")
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
GROUP(-lc -lpmon -lgcc)
|
||||
SEARCH_DIR(.)
|
||||
__DYNAMIC = 0;
|
||||
|
||||
/*
|
||||
* Allocate the stack to be at the top of memory, since the stack
|
||||
* grows down
|
||||
*/
|
||||
PROVIDE (__stack = 0);
|
||||
/* PROVIDE (__global = 0); */
|
||||
|
||||
/*
|
||||
* 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 multiple object file
|
||||
* formats, as some prepend an underscore.
|
||||
*/
|
||||
PROVIDE (hardware_init_hook = 0);
|
||||
PROVIDE (software_init_hook = 0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xA0020000;
|
||||
.text : {
|
||||
_ftext = . ;
|
||||
*(.init)
|
||||
eprol = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.mips16.fn.*)
|
||||
*(.mips16.call.*)
|
||||
PROVIDE (__runtime_reloc_start = .);
|
||||
*(.rel.sdata)
|
||||
PROVIDE (__runtime_reloc_stop = .);
|
||||
*(.fini)
|
||||
etext = .;
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
. = .;
|
||||
.rodata : {
|
||||
*(.rdata)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
}
|
||||
_fdata = ALIGN(16);
|
||||
.data : {
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
}
|
||||
. = ALIGN(8);
|
||||
_gp = . + 0x8000;
|
||||
__global = _gp;
|
||||
.lit8 : {
|
||||
*(.lit8)
|
||||
}
|
||||
.lit4 : {
|
||||
*(.lit4)
|
||||
}
|
||||
.sdata : {
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s*)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
edata = .;
|
||||
_edata = .;
|
||||
_fbss = .;
|
||||
.sbss : {
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
.bss : {
|
||||
_bss_start = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
end = .;
|
||||
_end = .;
|
||||
|
||||
/* 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) }
|
||||
}
|
151
libgloss/mips/regs.S
Normal file
151
libgloss/mips/regs.S
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* regs.S -- standard MIPS register names.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Standard MIPS register names: */
|
||||
#define zero $0
|
||||
#define z0 $0
|
||||
#define v0 $2
|
||||
#define v1 $3
|
||||
#define a0 $4
|
||||
#define a1 $5
|
||||
#define a2 $6
|
||||
#define a3 $7
|
||||
#define t0 $8
|
||||
#define t1 $9
|
||||
#define t2 $10
|
||||
#define t3 $11
|
||||
#define t4 $12
|
||||
#define t5 $13
|
||||
#define t6 $14
|
||||
#define t7 $15
|
||||
#define s0 $16
|
||||
#define s1 $17
|
||||
#define s2 $18
|
||||
#define s3 $19
|
||||
#define s4 $20
|
||||
#define s5 $21
|
||||
#define s6 $22
|
||||
#define s7 $23
|
||||
#define t8 $24
|
||||
#define t9 $25
|
||||
#define k0 $26 /* kernel private register 0 */
|
||||
#define k1 $27 /* kernel private register 1 */
|
||||
#define gp $28 /* global data pointer */
|
||||
#define sp $29 /* stack-pointer */
|
||||
#define fp $30 /* frame-pointer */
|
||||
#define ra $31 /* return address */
|
||||
#define pc $pc /* pc, used on mips16 */
|
||||
|
||||
#define fp0 $f0
|
||||
#define fp1 $f1
|
||||
|
||||
/* Useful memory constants: */
|
||||
#define K0BASE 0x80000000
|
||||
#ifndef __mips64
|
||||
#define K1BASE 0xA0000000
|
||||
#else
|
||||
#define K1BASE 0xFFFFFFFFA0000000LL
|
||||
#endif
|
||||
|
||||
#define PHYS_TO_K1(a) ((unsigned)(a) | K1BASE)
|
||||
|
||||
/* Standard Co-Processor 0 register numbers:
|
||||
#define C0_COUNT $9 /* Count Register */
|
||||
#define C0_SR $12 /* Status Register */
|
||||
#define C0_CAUSE $13 /* last exception description */
|
||||
#define C0_EPC $14 /* Exception error address */
|
||||
#define C0_PRID $15 /* Processor Revision ID */
|
||||
#define C0_CONFIG $16 /* CPU configuration */
|
||||
|
||||
/* Standard Processor Revision ID Register field offsets */
|
||||
#define PR_IMP 8
|
||||
|
||||
/* Standard Config Register field offsets */
|
||||
#define CR_DB 4
|
||||
#define CR_IB 5
|
||||
#define CR_DC 6 /* NOTE v4121 semantics != 43,5xxx semantics */
|
||||
#define CR_IC 9 /* NOTE v4121 semantics != 43,5xxx semantics */
|
||||
#define CR_SC 17
|
||||
#define CR_SS 20
|
||||
#define CR_SB 22
|
||||
|
||||
|
||||
/* Standard Status Register bitmasks: */
|
||||
#define SR_CU1 0x20000000 /* Mark CP1 as usable */
|
||||
#define SR_FR 0x04000000 /* Enable MIPS III FP registers */
|
||||
#define SR_BEV 0x00400000 /* Controls location of exception vectors */
|
||||
#define SR_PE 0x00100000 /* Mark soft reset (clear parity error) */
|
||||
|
||||
#define SR_KX 0x00000080 /* Kernel extended addressing enabled */
|
||||
#define SR_SX 0x00000040 /* Supervisor extended addressing enabled */
|
||||
#define SR_UX 0x00000020 /* User extended addressing enabled */
|
||||
|
||||
/* Standard (R4000) cache operations. Taken from "MIPS R4000
|
||||
Microprocessor User's Manual" 2nd edition: */
|
||||
|
||||
#define CACHE_I (0) /* primary instruction */
|
||||
#define CACHE_D (1) /* primary data */
|
||||
#define CACHE_SI (2) /* secondary instruction */
|
||||
#define CACHE_SD (3) /* secondary data (or combined instruction/data) */
|
||||
|
||||
#define INDEX_INVALIDATE (0) /* also encodes WRITEBACK if CACHE_D or CACHE_SD */
|
||||
#define INDEX_LOAD_TAG (1)
|
||||
#define INDEX_STORE_TAG (2)
|
||||
#define CREATE_DIRTY_EXCLUSIVE (3) /* CACHE_D and CACHE_SD only */
|
||||
#define HIT_INVALIDATE (4)
|
||||
#define CACHE_FILL (5) /* CACHE_I only */
|
||||
#define HIT_WRITEBACK_INVALIDATE (5) /* CACHE_D and CACHE_SD only */
|
||||
#define HIT_WRITEBACK (6) /* CACHE_I, CACHE_D and CACHE_SD only */
|
||||
#define HIT_SET_VIRTUAL (7) /* CACHE_SI and CACHE_SD only */
|
||||
|
||||
#define BUILD_CACHE_OP(o,c) (((o) << 2) | (c))
|
||||
|
||||
/* Individual cache operations: */
|
||||
#define INDEX_INVALIDATE_I BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_I)
|
||||
#define INDEX_WRITEBACK_INVALIDATE_D BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_D)
|
||||
#define INDEX_INVALIDATE_SI BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_SI)
|
||||
#define INDEX_WRITEBACK_INVALIDATE_SD BUILD_CACHE_OP(INDEX_INVALIDATE,CACHE_SD)
|
||||
|
||||
#define INDEX_LOAD_TAG_I BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_I)
|
||||
#define INDEX_LOAD_TAG_D BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_D)
|
||||
#define INDEX_LOAD_TAG_SI BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_SI)
|
||||
#define INDEX_LOAD_TAG_SD BUILD_CACHE_OP(INDEX_LOAD_TAG,CACHE_SD)
|
||||
|
||||
#define INDEX_STORE_TAG_I BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_I)
|
||||
#define INDEX_STORE_TAG_D BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_D)
|
||||
#define INDEX_STORE_TAG_SI BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_SI)
|
||||
#define INDEX_STORE_TAG_SD BUILD_CACHE_OP(INDEX_STORE_TAG,CACHE_SD)
|
||||
|
||||
#define CREATE_DIRTY_EXCLUSIVE_D BUILD_CACHE_OP(CREATE_DIRTY_EXCLUSIVE,CACHE_D)
|
||||
#define CREATE_DIRTY_EXCLUSIVE_SD BUILD_CACHE_OP(CREATE_DIRTY_EXCLUSIVE,CACHE_SD)
|
||||
|
||||
#define HIT_INVALIDATE_I BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_I)
|
||||
#define HIT_INVALIDATE_D BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_D)
|
||||
#define HIT_INVALIDATE_SI BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_SI)
|
||||
#define HIT_INVALIDATE_SD BUILD_CACHE_OP(HIT_INVALIDATE,CACHE_SD)
|
||||
|
||||
#define CACHE_FILL_I BUILD_CACHE_OP(CACHE_FILL,CACHE_I)
|
||||
#define HIT_WRITEBACK_INVALIDATE_D BUILD_CACHE_OP(HIT_WRITEBACK_INVALIDATE,CACHE_D)
|
||||
#define HIT_WRITEBACK_INVALIDATE_SD BUILD_CACHE_OP(HIT_WRITEBACK_INVALIDATE,CACHE_SD)
|
||||
|
||||
#define HIT_WRITEBACK_I BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_I)
|
||||
#define HIT_WRITEBACK_D BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_D)
|
||||
#define HIT_WRITEBACK_SD BUILD_CACHE_OP(HIT_WRITEBACK,CACHE_SD)
|
||||
|
||||
#define HIT_SET_VIRTUAL_SI BUILD_CACHE_OP(HIT_SET_VIRTUAL,CACHE_SI)
|
||||
#define HIT_SET_VIRTUAL_SD BUILD_CACHE_OP(HIT_SET_VIRTUAL,CACHE_SD)
|
||||
|
||||
/*> EOF regs.S <*/
|
45
libgloss/mips/syscalls.c
Normal file
45
libgloss/mips/syscalls.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include <_ansi.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
extern char _end[];
|
||||
|
||||
/* FIXME: This is not ideal, since we do a get_mem_info() call for
|
||||
every sbrk() call. */
|
||||
char *
|
||||
sbrk (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
static char *heap_ptr = _end;
|
||||
static char *heap_start = _end;
|
||||
char *base;
|
||||
struct s_mem {
|
||||
unsigned int size;
|
||||
unsigned int icsize;
|
||||
unsigned int dcsize;
|
||||
} mem;
|
||||
unsigned int avail = 0;
|
||||
|
||||
/* The sizeof (s_mem.size) must be 4 bytes. The compiler should be
|
||||
able to eliminate this check */
|
||||
if (sizeof (unsigned int) != 4)
|
||||
return (char *)-1;
|
||||
|
||||
get_mem_info(&mem);
|
||||
/* NOTE: The value returned from the get_mem_info call is the amount
|
||||
of memory, and not the address of the (last byte + 1) */
|
||||
|
||||
if (((size_t)heap_ptr >= heap_start) && ((size_t)heap_ptr < (heap_start + mem.size))) {
|
||||
avail = (heap_start + mem.size) - (size_t)heap_ptr;
|
||||
base = heap_ptr;
|
||||
} /* else will fail since "nbytes" will be greater than zeroed "avail" value */
|
||||
|
||||
if ((nbytes > avail) || (heap_ptr + nbytes < _end))
|
||||
base = (char *)-1;
|
||||
else
|
||||
heap_ptr += nbytes;
|
||||
|
||||
return base;
|
||||
}
|
13
libgloss/mips/test.c
Normal file
13
libgloss/mips/test.c
Normal file
@ -0,0 +1,13 @@
|
||||
main()
|
||||
{
|
||||
outbyte ('&');
|
||||
outbyte ('@');
|
||||
outbyte ('$');
|
||||
outbyte ('%');
|
||||
|
||||
/* whew, we made it */
|
||||
|
||||
print ("\r\nDone...");
|
||||
|
||||
return;
|
||||
}
|
341
libgloss/mips/vr4300.S
Normal file
341
libgloss/mips/vr4300.S
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* vr4300.S -- CPU specific support routines
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __mips64
|
||||
.set mips3
|
||||
#endif
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
# Taken from "R4300 Preliminary RISC Processor Specification
|
||||
# Revision 2.0 January 1995" page 39: "The Count
|
||||
# register... increments at a constant rate... at one-half the
|
||||
# PClock speed."
|
||||
# We can use this fact to provide small polled delays.
|
||||
.globl __cpu_timer_poll
|
||||
.ent __cpu_timer_poll
|
||||
__cpu_timer_poll:
|
||||
.set noreorder
|
||||
# in: a0 = (unsigned int) number of PClock ticks to wait for
|
||||
# out: void
|
||||
|
||||
# The Vr4300 counter updates at half PClock, so divide by 2 to
|
||||
# get counter delta:
|
||||
bnezl a0, 1f # continue if delta non-zero
|
||||
srl a0, a0, 1 # divide ticks by 2 {DELAY SLOT}
|
||||
# perform a quick return to the caller:
|
||||
j ra
|
||||
nop # {DELAY SLOT}
|
||||
1:
|
||||
mfc0 v0, $9 # C0_COUNT: get current counter value
|
||||
nop
|
||||
nop
|
||||
# We cannot just do the simple test, of adding our delta onto
|
||||
# the current value (ignoring overflow) and then checking for
|
||||
# equality. The counter is incrementing every two PClocks,
|
||||
# which means the counter value can change between
|
||||
# instructions, making it hard to sample at the exact value
|
||||
# desired.
|
||||
|
||||
# However, we do know that our entry delta value is less than
|
||||
# half the number space (since we divide by 2 on entry). This
|
||||
# means we can use a difference in signs to indicate timer
|
||||
# overflow.
|
||||
addu a0, v0, a0 # unsigned add (ignore overflow)
|
||||
# We know have our end value (which will have been
|
||||
# sign-extended to fill the 64bit register value).
|
||||
2:
|
||||
# get current counter value:
|
||||
mfc0 v0, $9 # C0_COUNT
|
||||
nop
|
||||
nop
|
||||
# This is an unsigned 32bit subtraction:
|
||||
subu v0, a0, v0 # delta = (end - now) {DELAY SLOT}
|
||||
bgtzl v0, 2b # looping back is most likely
|
||||
nop
|
||||
# We have now been delayed (in the foreground) for AT LEAST
|
||||
# the required number of counter ticks.
|
||||
j ra # return to caller
|
||||
nop # {DELAY SLOT}
|
||||
.set reorder
|
||||
.end __cpu_timer_poll
|
||||
|
||||
# Flush the processor caches to memory:
|
||||
|
||||
.globl __cpu_flush
|
||||
.ent __cpu_flush
|
||||
__cpu_flush:
|
||||
.set noreorder
|
||||
# NOTE: The Vr4300 *CANNOT* have any secondary cache (bit 17
|
||||
# of the CONFIG registered is hard-wired to 1). We just
|
||||
# provide code to flush the Data and Instruction caches.
|
||||
|
||||
# Even though the Vr4300 has hard-wired cache and cache line
|
||||
# sizes, we still interpret the relevant Config register
|
||||
# bits. This allows this code to be used for other conforming
|
||||
# MIPS architectures if desired.
|
||||
|
||||
# Get the config register
|
||||
mfc0 a0, C0_CONFIG
|
||||
nop
|
||||
nop
|
||||
li a1, 1 # a useful constant
|
||||
#
|
||||
srl a2, a0, 9 # bits 11..9 for instruction cache size
|
||||
andi a2, a2, 0x7 # 3bits of information
|
||||
add a2, a2, 12 # get full power-of-2 value
|
||||
sllv a2, a1, a2 # instruction cache size
|
||||
#
|
||||
srl a3, a0, 6 # bits 8..6 for data cache size
|
||||
andi a3, a3, 0x7 # 3bits of information
|
||||
add a3, a3, 12 # get full power-of-2 value
|
||||
sllv a3, a1, a3 # data cache size
|
||||
#
|
||||
li a1, (1 << 5) # check IB (instruction cache line size)
|
||||
and a1, a0, a1 # mask against the CONFIG register value
|
||||
beqz a1, 1f # branch on result of delay slot operation
|
||||
nop
|
||||
li a1, 32 # non-zero, then 32bytes
|
||||
j 2f # continue
|
||||
nop
|
||||
1:
|
||||
li a1, 16 # 16bytes
|
||||
2:
|
||||
#
|
||||
li t0, (1 << 4) # check DB (data cache line size)
|
||||
and a0, a0, t0 # mask against the CONFIG register value
|
||||
beqz a0, 3f # branch on result of delay slot operation
|
||||
nop
|
||||
li a0, 32 # non-zero, then 32bytes
|
||||
j 4f # continue
|
||||
nop
|
||||
3:
|
||||
li a0, 16 # 16bytes
|
||||
4:
|
||||
#
|
||||
# a0 = data cache line size
|
||||
# a1 = instruction cache line size
|
||||
# a2 = instruction cache size
|
||||
# a3 = data cache size
|
||||
#
|
||||
lui t0, ((K0BASE >> 16) & 0xFFFF)
|
||||
ori t0, t0, (K0BASE & 0xFFFF)
|
||||
addu t1, t0, a2 # end cache address
|
||||
subu t2, a1, 1 # line size mask
|
||||
not t2 # invert the mask
|
||||
and t3, t0, t2 # get start address
|
||||
addu t1, -1
|
||||
and t1, t2 # get end address
|
||||
5:
|
||||
cache INDEX_INVALIDATE_I,0(t3)
|
||||
bne t3, t1, 5b
|
||||
addu t3, a1
|
||||
#
|
||||
addu t1, t0, a3 # end cache address
|
||||
subu t2, a0, 1 # line size mask
|
||||
not t2 # invert the mask
|
||||
and t3, t0, t2 # get start address
|
||||
addu t1, -1
|
||||
and t1, t2 # get end address
|
||||
6:
|
||||
cache INDEX_WRITEBACK_INVALIDATE_D,0(t3)
|
||||
bne t3, t1, 6b
|
||||
addu t3, a0
|
||||
#
|
||||
j ra # return to the caller
|
||||
nop
|
||||
.set reorder
|
||||
.end __cpu_flush
|
||||
|
||||
# NOTE: This variable should *NOT* be addressed relative to
|
||||
# the $gp register since this code is executed before $gp is
|
||||
# initialised... hence we leave it in the text area. This will
|
||||
# cause problems if this routine is ever ROMmed:
|
||||
|
||||
.globl __buserr_cnt
|
||||
__buserr_cnt:
|
||||
.word 0
|
||||
.align 3
|
||||
__k1_save:
|
||||
.word 0
|
||||
.word 0
|
||||
.align 2
|
||||
|
||||
.ent __buserr
|
||||
.globl __buserr
|
||||
__buserr:
|
||||
.set noat
|
||||
.set noreorder
|
||||
# k0 and k1 available for use:
|
||||
mfc0 k0,C0_CAUSE
|
||||
nop
|
||||
nop
|
||||
andi k0,k0,0x7c
|
||||
sub k0,k0,7 << 2
|
||||
beq k0,$0,__buserr_do
|
||||
nop
|
||||
# call the previous handler
|
||||
la k0,__previous
|
||||
jr k0
|
||||
nop
|
||||
#
|
||||
__buserr_do:
|
||||
# TODO: check that the cause is indeed a bus error
|
||||
# - if not then just jump to the previous handler
|
||||
la k0,__k1_save
|
||||
sd k1,0(k0)
|
||||
#
|
||||
la k1,__buserr_cnt
|
||||
lw k0,0(k1) # increment counter
|
||||
addu k0,1
|
||||
sw k0,0(k1)
|
||||
#
|
||||
la k0,__k1_save
|
||||
ld k1,0(k0)
|
||||
#
|
||||
mfc0 k0,C0_EPC
|
||||
nop
|
||||
nop
|
||||
addu k0,k0,4 # skip offending instruction
|
||||
mtc0 k0,C0_EPC # update EPC
|
||||
nop
|
||||
nop
|
||||
eret
|
||||
# j k0
|
||||
# rfe
|
||||
.set reorder
|
||||
.set at
|
||||
.end __buserr
|
||||
|
||||
__exception_code:
|
||||
.set noreorder
|
||||
lui k0,%hi(__buserr)
|
||||
daddiu k0,k0,%lo(__buserr)
|
||||
jr k0
|
||||
nop
|
||||
.set reorder
|
||||
__exception_code_end:
|
||||
|
||||
.data
|
||||
__previous:
|
||||
.space (__exception_code_end - __exception_code)
|
||||
# This subtracting two addresses is working
|
||||
# but is not garenteed to continue working.
|
||||
# The assemble reserves the right to put these
|
||||
# two labels into different frags, and then
|
||||
# cant take their difference.
|
||||
|
||||
.text
|
||||
|
||||
.ent __default_buserr_handler
|
||||
.globl __default_buserr_handler
|
||||
__default_buserr_handler:
|
||||
.set noreorder
|
||||
# attach our simple bus error handler:
|
||||
# in: void
|
||||
# out: void
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,baseaddr
|
||||
lui a0,0x8000 # delay slot
|
||||
lui a0,0xbfc0
|
||||
daddiu a0,a0,0x0200
|
||||
baseaddr:
|
||||
daddiu a0,a0,0x0180
|
||||
# a0 = base vector table address
|
||||
la a1,__exception_code_end
|
||||
la a2,__exception_code
|
||||
subu a1,a1,a2
|
||||
la a3,__previous
|
||||
# there must be a better way of doing this????
|
||||
copyloop:
|
||||
lw v0,0(a0)
|
||||
sw v0,0(a3)
|
||||
lw v0,0(a2)
|
||||
sw v0,0(a0)
|
||||
daddiu a0,a0,4
|
||||
daddiu a2,a2,4
|
||||
daddiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,copyloop
|
||||
nop
|
||||
la a0,__buserr_cnt
|
||||
sw $0,0(a0)
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __default_buserr_handler
|
||||
|
||||
.ent __restore_buserr_handler
|
||||
.globl __restore_buserr_handler
|
||||
__restore_buserr_handler:
|
||||
.set noreorder
|
||||
# restore original (monitor) bus error handler
|
||||
# in: void
|
||||
# out: void
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,res_baseaddr
|
||||
lui a0,0x8000 # delay slot
|
||||
lui a0,0xbfc0
|
||||
daddiu a0,a0,0x0200
|
||||
res_baseaddr:
|
||||
daddiu a0,a0,0x0180
|
||||
# a0 = base vector table address
|
||||
la a1,__exception_code_end
|
||||
la a3,__exception_code
|
||||
subu a1,a1,a3
|
||||
la a3,__previous
|
||||
# there must be a better way of doing this????
|
||||
res_copyloop:
|
||||
lw v0,0(a3)
|
||||
sw v0,0(a0)
|
||||
daddiu a0,a0,4
|
||||
daddiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,res_copyloop
|
||||
nop
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __restore_buserr_handler
|
||||
|
||||
.ent __buserr_count
|
||||
.globl __buserr_count
|
||||
__buserr_count:
|
||||
.set noreorder
|
||||
# restore original (monitor) bus error handler
|
||||
# in: void
|
||||
# out: unsigned int __buserr_cnt
|
||||
la v0,__buserr_cnt
|
||||
lw v0,0(v0)
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __buserr_count
|
||||
|
||||
/* EOF vr4300.S */
|
457
libgloss/mips/vr5xxx.S
Normal file
457
libgloss/mips/vr5xxx.S
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* vr5xxx.S -- CPU specific support routines
|
||||
*
|
||||
* Copyright (c) 1999 Cygnus Solutions
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This file cloned from vr4300.S by dlindsay@cygnus.com
|
||||
* and recoded to suit Vr5432 and Vr5000.
|
||||
* Should be no worse for Vr43{00,05,10}.
|
||||
* Specifically, __cpu_flush() has been changed (a) to allow for the hardware
|
||||
* difference (in set associativity) between the Vr5432 and Vr5000,
|
||||
* and (b) to flush the optional secondary cache of the Vr5000.
|
||||
*/
|
||||
|
||||
/* Processor Revision Identifier (PRID) Register: Implementation Numbers */
|
||||
#define IMPL_VR5432 0x54
|
||||
|
||||
/* Cache Constants not determinable dynamically */
|
||||
#define VR5000_2NDLINE 32 /* secondary cache line size */
|
||||
#define VR5432_LINE 32 /* I,Dcache line sizes */
|
||||
#define VR5432_SIZE (16*1024) /* I,Dcache half-size */
|
||||
|
||||
|
||||
#ifndef __mips64
|
||||
.set mips3
|
||||
#endif
|
||||
#ifdef __mips16
|
||||
/* This file contains 32 bit assembly code. */
|
||||
.set nomips16
|
||||
#endif
|
||||
|
||||
#include "regs.S"
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
# Taken from "R4300 Preliminary RISC Processor Specification
|
||||
# Revision 2.0 January 1995" page 39: "The Count
|
||||
# register... increments at a constant rate... at one-half the
|
||||
# PClock speed."
|
||||
# We can use this fact to provide small polled delays.
|
||||
.globl __cpu_timer_poll
|
||||
.ent __cpu_timer_poll
|
||||
__cpu_timer_poll:
|
||||
.set noreorder
|
||||
# in: a0 = (unsigned int) number of PClock ticks to wait for
|
||||
# out: void
|
||||
|
||||
# The Vr4300 counter updates at half PClock, so divide by 2 to
|
||||
# get counter delta:
|
||||
bnezl a0, 1f # continue if delta non-zero
|
||||
srl a0, a0, 1 # divide ticks by 2 {DELAY SLOT}
|
||||
# perform a quick return to the caller:
|
||||
j ra
|
||||
nop # {DELAY SLOT}
|
||||
1:
|
||||
mfc0 v0, $9 # C0_COUNT: get current counter value
|
||||
nop
|
||||
nop
|
||||
# We cannot just do the simple test, of adding our delta onto
|
||||
# the current value (ignoring overflow) and then checking for
|
||||
# equality. The counter is incrementing every two PClocks,
|
||||
# which means the counter value can change between
|
||||
# instructions, making it hard to sample at the exact value
|
||||
# desired.
|
||||
|
||||
# However, we do know that our entry delta value is less than
|
||||
# half the number space (since we divide by 2 on entry). This
|
||||
# means we can use a difference in signs to indicate timer
|
||||
# overflow.
|
||||
addu a0, v0, a0 # unsigned add (ignore overflow)
|
||||
# We know have our end value (which will have been
|
||||
# sign-extended to fill the 64bit register value).
|
||||
2:
|
||||
# get current counter value:
|
||||
mfc0 v0, $9 # C0_COUNT
|
||||
nop
|
||||
nop
|
||||
# This is an unsigned 32bit subtraction:
|
||||
subu v0, a0, v0 # delta = (end - now) {DELAY SLOT}
|
||||
bgtzl v0, 2b # looping back is most likely
|
||||
nop
|
||||
# We have now been delayed (in the foreground) for AT LEAST
|
||||
# the required number of counter ticks.
|
||||
j ra # return to caller
|
||||
nop # {DELAY SLOT}
|
||||
.set reorder
|
||||
.end __cpu_timer_poll
|
||||
|
||||
# Flush the processor caches to memory:
|
||||
|
||||
.globl __cpu_flush
|
||||
.ent __cpu_flush
|
||||
__cpu_flush:
|
||||
.set noreorder
|
||||
# NOTE: The Vr4300 and Vr5432 *CANNOT* have any secondary cache.
|
||||
# On those, SC (bit 17 of CONFIG register) is hard-wired to 1,
|
||||
# except that email from Dennis_Han@el.nec.com says that old
|
||||
# versions of the Vr5432 incorrectly hard-wired this bit to 0.
|
||||
# The Vr5000 has an optional direct-mapped secondary cache,
|
||||
# and the SC bit correctly indicates this.
|
||||
|
||||
# So, for the 4300 and 5432 we want to just
|
||||
# flush the primary Data and Instruction caches.
|
||||
# For the 5000 it is desired to flush the secondary cache too.
|
||||
# There is an operation difference worth noting.
|
||||
# The 4300 and 5000 primary caches use VA bit 14 to choose cache set,
|
||||
# whereas 5432 primary caches use VA bit 0.
|
||||
|
||||
# This code interprets the relevant Config register bits as
|
||||
# much as possible, except for the 5432.
|
||||
# The code therefore has some portability.
|
||||
# However, the associativity issues mean you should not just assume
|
||||
# that this code works anywhere. Also, the secondary cache set
|
||||
# size is hardwired, since the 5000 series does not define codes
|
||||
# for variant sizes.
|
||||
|
||||
# Note: this version of the code flushes D$ before I$.
|
||||
# It is difficult to construct a case where that matters,
|
||||
# but it cant hurt.
|
||||
|
||||
mfc0 a0, C0_PRID # a0 = Processor Revision register
|
||||
nop # dlindsay: unclear why the nops, but
|
||||
nop # vr4300.S had such so I do too.
|
||||
srl a2, a0, PR_IMP # want bits 8..15
|
||||
andi a2, a2, 0x255 # mask: now a2 = Implementation # field
|
||||
li a1, IMPL_VR5432
|
||||
beq a1, a2, 8f # use Vr5432-specific flush algorithm
|
||||
nop
|
||||
|
||||
# Non-Vr5432 version of the code.
|
||||
# (The distinctions being: CONFIG is truthful about secondary cache,
|
||||
# and we act as if the primary Icache and Dcache are direct mapped.)
|
||||
|
||||
mfc0 t0, C0_CONFIG # t0 = CONFIG register
|
||||
nop
|
||||
nop
|
||||
li a1, 1 # a1=1, a useful constant
|
||||
|
||||
srl a2, t0, CR_IC # want IC field of CONFIG
|
||||
andi a2, a2, 0x7 # mask: now a2= code for Icache size
|
||||
add a2, a2, 12 # +12
|
||||
sllv a2, a1, a2 # a2=primary instruction cache size in bytes
|
||||
|
||||
srl a3, t0, CR_DC # DC field of CONFIG
|
||||
andi a3, a3, 0x7 # mask: now a3= code for Dcache size
|
||||
add a3, a3, 12 # +12
|
||||
sllv a3, a1, a3 # a3=primary data cache size in bytes
|
||||
|
||||
li t2, (1 << CR_IB) # t2=mask over IB boolean
|
||||
and t2, t2, t0 # test IB field of CONFIG register value
|
||||
beqz t2, 1f #
|
||||
li a1, 16 # 16 bytes (branch shadow: always loaded.)
|
||||
li a1, 32 # non-zero, then 32bytes
|
||||
1:
|
||||
|
||||
li t2, (1 << CR_DB) # t2=mask over DB boolean
|
||||
and t2, t2, t0 # test BD field of CONFIG register value
|
||||
beqz t2, 2f #
|
||||
li a0, 16 # 16bytes (branch shadow: always loaded.)
|
||||
li a0, 32 # non-zero, then 32bytes
|
||||
2:
|
||||
lui t1, ((K0BASE >> 16) & 0xFFFF)
|
||||
ori t1, t1, (K0BASE & 0xFFFF)
|
||||
|
||||
# At this point,
|
||||
# a0 = primary Dcache line size in bytes
|
||||
# a1 = primary Icache line size in bytes
|
||||
# a2 = primary Icache size in bytes
|
||||
# a3 = primary Dcache size in bytes
|
||||
# t0 = CONFIG value
|
||||
# t1 = a round unmapped cached base address (we are in kernel mode)
|
||||
# t2,t3 scratch
|
||||
|
||||
addi t3, t1, 0 # t3=t1=start address for any cache
|
||||
add t2, t3, a3 # t2=end adress+1 of Dcache
|
||||
sub t2, t2, a0 # t2=address of last line in Dcache
|
||||
3:
|
||||
cache INDEX_WRITEBACK_INVALIDATE_D,0(t3)
|
||||
bne t3, t2, 3b #
|
||||
addu t3, a0 # (delay slot) increment by Dcache line size
|
||||
|
||||
|
||||
# Now check CONFIG to see if there is a secondary cache
|
||||
lui t2, (1 << (CR_SC-16)) # t2=mask over SC boolean
|
||||
and t2, t2, t0 # test SC in CONFIG
|
||||
bnez t2, 6f
|
||||
|
||||
# There is a secondary cache. Find out its sizes.
|
||||
|
||||
srl t3, t0, CR_SS # want SS field of CONFIG
|
||||
andi t3, t3, 0x3 # mask: now t3= code for cache size.
|
||||
beqz t3, 4f
|
||||
lui a3, ((512*1024)>>16) # a3= 512K, code was 0
|
||||
addu t3, -1 # decrement code
|
||||
beqz t3, 4f
|
||||
lui a3, ((1024*1024)>>16) # a3= 1 M, code 1
|
||||
addu t3, -1 # decrement code
|
||||
beqz t3, 4f
|
||||
lui a3, ((2*1024*1024)>>16) # a3= 2 M, code 2
|
||||
j 6f # no secondary cache, code 3
|
||||
|
||||
4: # a3 = secondary cache size in bytes
|
||||
li a0, VR5000_2NDLINE # no codes assigned for other than 32
|
||||
|
||||
# At this point,
|
||||
# a0 = secondary cache line size in bytes
|
||||
# a1 = primary Icache line size in bytes
|
||||
# a2 = primary Icache size in bytes
|
||||
# a3 = secondary cache size in bytes
|
||||
# t1 = a round unmapped cached base address (we are in kernel mode)
|
||||
# t2,t3 scratch
|
||||
|
||||
addi t3, t1, 0 # t3=t1=start address for any cache
|
||||
add t2, t3, a3 # t2=end address+1 of secondary cache
|
||||
sub t2, t2, a0 # t2=address of last line in secondary cache
|
||||
5:
|
||||
cache INDEX_WRITEBACK_INVALIDATE_SD,0(t3)
|
||||
bne t3, t2, 5b
|
||||
addu t3, a0 # (delay slot) increment by line size
|
||||
|
||||
|
||||
6: # Any optional secondary cache done. Now do I-cache and return.
|
||||
|
||||
# At this point,
|
||||
# a1 = primary Icache line size in bytes
|
||||
# a2 = primary Icache size in bytes
|
||||
# t1 = a round unmapped cached base address (we are in kernel mode)
|
||||
# t2,t3 scratch
|
||||
|
||||
add t2, t1, a2 # t2=end adress+1 of Icache
|
||||
sub t2, t2, a1 # t2=address of last line in Icache
|
||||
7:
|
||||
cache INDEX_INVALIDATE_I,0(t1)
|
||||
bne t1, t2, 7b
|
||||
addu t1, a1 # (delay slot) increment by Icache line size
|
||||
|
||||
j ra # return to the caller
|
||||
nop
|
||||
|
||||
8:
|
||||
|
||||
# Vr5432 version of the cpu_flush code.
|
||||
# (The distinctions being: CONFIG can not be trusted about secondary
|
||||
# cache (which does not exist). The primary caches use Virtual Address Bit 0
|
||||
# to control set selection.
|
||||
|
||||
# Code does not consult CONFIG about cache sizes: knows the hardwired sizes.
|
||||
# Since both I and D have the same size and line size, uses a merged loop.
|
||||
|
||||
li a0, VR5432_LINE
|
||||
li a1, VR5432_SIZE
|
||||
lui t1, ((K0BASE >> 16) & 0xFFFF)
|
||||
ori t1, t1, (K0BASE & 0xFFFF)
|
||||
|
||||
# a0 = cache line size in bytes
|
||||
# a1 = 1/2 cache size in bytes
|
||||
# t1 = a round unmapped cached base address (we are in kernel mode)
|
||||
|
||||
add t2, t1, a1 # t2=end address+1
|
||||
sub t2, t2, a0 # t2=address of last line in Icache
|
||||
|
||||
9:
|
||||
cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) # set 0
|
||||
cache INDEX_WRITEBACK_INVALIDATE_D,1(t1) # set 1
|
||||
cache INDEX_INVALIDATE_I,0(t1) # set 0
|
||||
cache INDEX_INVALIDATE_I,1(t1) # set 1
|
||||
bne t1, t2, 9b
|
||||
addu t1, a0
|
||||
|
||||
j ra # return to the caller
|
||||
nop
|
||||
.set reorder
|
||||
.end __cpu_flush
|
||||
|
||||
# NOTE: This variable should *NOT* be addressed relative to
|
||||
# the $gp register since this code is executed before $gp is
|
||||
# initialised... hence we leave it in the text area. This will
|
||||
# cause problems if this routine is ever ROMmed:
|
||||
|
||||
.globl __buserr_cnt
|
||||
__buserr_cnt:
|
||||
.word 0
|
||||
.align 3
|
||||
__k1_save:
|
||||
.word 0
|
||||
.word 0
|
||||
.align 2
|
||||
|
||||
.ent __buserr
|
||||
.globl __buserr
|
||||
__buserr:
|
||||
.set noat
|
||||
.set noreorder
|
||||
# k0 and k1 available for use:
|
||||
mfc0 k0,C0_CAUSE
|
||||
nop
|
||||
nop
|
||||
andi k0,k0,0x7c
|
||||
sub k0,k0,7 << 2
|
||||
beq k0,$0,__buserr_do
|
||||
nop
|
||||
# call the previous handler
|
||||
la k0,__previous
|
||||
jr k0
|
||||
nop
|
||||
#
|
||||
__buserr_do:
|
||||
# TODO: check that the cause is indeed a bus error
|
||||
# - if not then just jump to the previous handler
|
||||
la k0,__k1_save
|
||||
sd k1,0(k0)
|
||||
#
|
||||
la k1,__buserr_cnt
|
||||
lw k0,0(k1) # increment counter
|
||||
addu k0,1
|
||||
sw k0,0(k1)
|
||||
#
|
||||
la k0,__k1_save
|
||||
ld k1,0(k0)
|
||||
#
|
||||
mfc0 k0,C0_EPC
|
||||
nop
|
||||
nop
|
||||
addu k0,k0,4 # skip offending instruction
|
||||
mtc0 k0,C0_EPC # update EPC
|
||||
nop
|
||||
nop
|
||||
eret
|
||||
# j k0
|
||||
# rfe
|
||||
.set reorder
|
||||
.set at
|
||||
.end __buserr
|
||||
|
||||
__exception_code:
|
||||
.set noreorder
|
||||
lui k0,%hi(__buserr)
|
||||
daddiu k0,k0,%lo(__buserr)
|
||||
jr k0
|
||||
nop
|
||||
.set reorder
|
||||
__exception_code_end:
|
||||
|
||||
.data
|
||||
__previous:
|
||||
.space (__exception_code_end - __exception_code)
|
||||
# This subtracting two addresses is working
|
||||
# but is not garenteed to continue working.
|
||||
# The assemble reserves the right to put these
|
||||
# two labels into different frags, and then
|
||||
# cant take their difference.
|
||||
|
||||
.text
|
||||
|
||||
.ent __default_buserr_handler
|
||||
.globl __default_buserr_handler
|
||||
__default_buserr_handler:
|
||||
.set noreorder
|
||||
# attach our simple bus error handler:
|
||||
# in: void
|
||||
# out: void
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,baseaddr
|
||||
lui a0,0x8000 # delay slot
|
||||
lui a0,0xbfc0
|
||||
daddiu a0,a0,0x0200
|
||||
baseaddr:
|
||||
daddiu a0,a0,0x0180
|
||||
# a0 = base vector table address
|
||||
la a1,__exception_code_end
|
||||
la a2,__exception_code
|
||||
subu a1,a1,a2
|
||||
la a3,__previous
|
||||
# there must be a better way of doing this????
|
||||
copyloop:
|
||||
lw v0,0(a0)
|
||||
sw v0,0(a3)
|
||||
lw v0,0(a2)
|
||||
sw v0,0(a0)
|
||||
daddiu a0,a0,4
|
||||
daddiu a2,a2,4
|
||||
daddiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,copyloop
|
||||
nop
|
||||
la a0,__buserr_cnt
|
||||
sw $0,0(a0)
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __default_buserr_handler
|
||||
|
||||
.ent __restore_buserr_handler
|
||||
.globl __restore_buserr_handler
|
||||
__restore_buserr_handler:
|
||||
.set noreorder
|
||||
# restore original (monitor) bus error handler
|
||||
# in: void
|
||||
# out: void
|
||||
mfc0 a0,C0_SR
|
||||
nop
|
||||
li a1,SR_BEV
|
||||
and a1,a1,a0
|
||||
beq a1,$0,res_baseaddr
|
||||
lui a0,0x8000 # delay slot
|
||||
lui a0,0xbfc0
|
||||
daddiu a0,a0,0x0200
|
||||
res_baseaddr:
|
||||
daddiu a0,a0,0x0180
|
||||
# a0 = base vector table address
|
||||
la a1,__exception_code_end
|
||||
la a3,__exception_code
|
||||
subu a1,a1,a3
|
||||
la a3,__previous
|
||||
# there must be a better way of doing this????
|
||||
res_copyloop:
|
||||
lw v0,0(a3)
|
||||
sw v0,0(a0)
|
||||
daddiu a0,a0,4
|
||||
daddiu a3,a3,4
|
||||
subu a1,a1,4
|
||||
bne a1,$0,res_copyloop
|
||||
nop
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __restore_buserr_handler
|
||||
|
||||
.ent __buserr_count
|
||||
.globl __buserr_count
|
||||
__buserr_count:
|
||||
.set noreorder
|
||||
# restore original (monitor) bus error handler
|
||||
# in: void
|
||||
# out: unsigned int __buserr_cnt
|
||||
la v0,__buserr_cnt
|
||||
lw v0,0(v0)
|
||||
j ra
|
||||
nop
|
||||
.set reorder
|
||||
.end __buserr_count
|
||||
|
||||
/* EOF vr5xxx.S */
|
Reference in New Issue
Block a user