From: adam Date: Tue, 16 Mar 2004 02:17:57 +0000 (-0800) Subject: imported brians code X-Git-Tag: merge~55 X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=commitdiff_plain;h=3eb15f58ca0911489d7d9bdc0ac2c575d27a68d8 imported brians code darcs-hash:20040316021757-5007d-1291b958e0af75914befcfde6fcfb47d2c6b25c3.gz --- diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3ea8fac --- /dev/null +++ b/Makefile @@ -0,0 +1,357 @@ +# +# What to build +# + +doc/nestedvm.ivme04.pdf: doc/nestedvm.ivme04.tex doc/acmconf.cls + cd doc; pdflatex nestedvm.ivme04.tex + +pdf: doc/nestedvm.ivme04.pdf + open doc/nestedvm.ivme04.pdf + +# Java sources that are part of the compiler/interpreter +java_sources = $(wildcard src/org/xwt/mips/*.java) $(wildcard src/org/xwt/mips/util/*.java) + +# Java sources that are part of the compiler/interpreter that are +# generated from other sources +java_gen_sources = $(patsubst %,build/org/xwt/mips/%.java, UsermodeConstants) + +# C sources that are part of the compiler/interpreter +mips_sources = crt0.c support_aux.c +mips_asm_sources = support.s + +mips2java_root = $(shell pwd) +build = $(mips2java_root)/build +tasks = upstream/tasks + +# +# MIPS Settings (don't change these) +# +flags = -march=mips1 +MIPS_CC = mips-unknown-elf-gcc +MIPS_CXX = mips-unknown-elf-g++ + +# Be VERY careful about changing any of these as they can break binary +# compatibility and create hard to find bugs +mips_optflags = -O3 -g \ + -fno-rename-registers -freduce-all-givs \ + -fno-peephole -fno-peephole2 -fmove-all-movables -fno-schedule-insns \ + -fno-delayed-branch \ + -mmemcpy \ + -ffunction-sections -fdata-sections \ + -falign-functions=512 + +MIPS_CFLAGS = $(mips_optflags) $(flags) -I. -Wall -Wno-unused -Werror +MIPS_LD = mips-unknown-elf-gcc +MIPS_LDFLAGS= \ + $(flags) -L$(build)/org/xwt/mips --static \ + -T $(mips2java_root)/src/org/xwt/mips/linker.ld -Wl,--gc-sections +MIPS_STRIP = mips-unknown-elf-strip + +# Java compiler/VM settings +JAVAC = javac +JAVA = java +ifeq ($(firstword $(JAVAC)),gcj) + JAVAC_NODEBUG_FLAGS = -g0 +else + JAVAC_NODEBUG_FLAGS = -g:none +endif + +CLASSPATH = build:upstream/build/bcel/bcel-5.1.jar + +GCJ = gcj +EXE_EXT = + +##### + +java_classes = \ + $(java_sources:src/%.java=build/%.class) \ + $(java_gen_sources:%.java=%.class) + +mips_objects = $(mips_sources:%.c=build/org/xwt/mips/%.o) $(mips_asm_sources:%.s=build/org/xwt/mips/%.o) + +.SECONDARY: + +PATH := $(mips2java_root)/upstream/install/bin:$(PATH) +export PATH + +# +# General Build Stuff +# +all: $(java_classes) $(mips_objects) +ifdef NATIVE_MIPS2JAVA_COMPILER +all: build/mips2java$(EXE_EXT) $(mips_objects) +endif + +$(tasks)/%: + $(MAKE) -C upstream tasks/$* MIPS_LDFLAGS="$(MIPS_LDFLAGS)" MIPS_CFLAGS="$(flags) $(mips_optflags)" + +upstream_clean_%: + $(MAKE) -C upstream clean_$* + +errno_h = upstream/install/mips-unknown-elf/include/sys/errno.h +$(errno_h): $(tasks)/build_newlib + +unistd_h = upstream/install/mips-unknown-elf/include/sys/unistd.h +$(unistd_h): $(tasks)/build_newlib + +# +# Interpreter/Compiler/Runtime Java Compilation +# + +# This works around a gcj -C bug +ifeq ($(firstword $(JAVAC)),gcj) +build/org/xwt/mips/util/.Dummy.class: + mkdir -p `dirname $@` + touch $@ +$(java_classes): build/org/xwt/mips/util/.Dummy.class +endif + +$(java_classes): $(tasks)/unpack_bcel $(java_sources) $(java_gen_sources) + $(JAVAC) -classpath $(CLASSPATH) -d build $(java_sources) $(java_gen_sources) + +build/org/xwt/mips/UsermodeConstants.java: src/org/xwt/mips/syscalls.h $(errno_h) $(unistd_h) + @mkdir -p `dirname $@` + cat $^ |\ + (FILE=org.xwt.mips.UsermodeConstants;\ + C="`echo $$FILE | sed 's/.*\.\([^\.]*\)$$/\1/;'`";\ + P="`echo $$FILE | sed -n 's/\(.*\)\..*/\1/p;'`";\ + [ -n "$$P" ] && echo "package $$P;";\ + echo "public interface $$C {";\ + tr '\t' ' ' | sed -n ';\ + s/ */ /g;\ + s/ *\# *define \([A-Z_][A-Za-z0-9_]*\) \([0-9][0-9x]*\)/ public static final int \1 = \2;/p';\ + echo "}") > $@ + + +# FIXME: We're cramming more than we need into the binary here +build/mips2java$(EXE_EXT): $(java_sources) $(java_gen_sources) + @mkdir -p `dirname $@` + $(GCJ) -s -o $@ --main=org.xwt.mips.Compiler $(java_sources) $(java_gen_sources) + +# +# MIPS Binary compilation +# +build/%.o: src/%.c $(tasks)/full_toolchain + @mkdir -p `dirname $@` + $(MIPS_CC) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) -c -o $@ $< + +build/%.o: src/%.s $(tasks)/full_toolchain + @mkdir -p `dirname $@` + $(MIPS_CC) -x assembler-with-cpp -c -o $@ $< + +%.s: %.c $(tasks)/full_toolchain + $(MIPS_CC) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) -c -S -o $@ $< + +build/%.mips: build/%.o $(mips_objects) + $(MIPS_LD) -o $@ $< $(MIPS_LDFLAGS) $($(notdir $*)_LDFLAGS) + +build/%.mips: src/%.cc $(tasks)/full_toolchain $(mips_objects) + @mkdir -p `dirname $@` + $(MIPS_CXX) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) $(MIPS_LDFLAGS) $($(notdir $*)_LDFLAGS) -o $@ $< + +build/%.mips.stripped: build/%.mips + cp $< $@ + $(MIPS_STRIP) -s $@ + +# MIPS Compiler generated class compilation +ifdef DO_JAVASOURCE + +build/%.java: build/%.mips build/org/xwt/mips/JavaSourceCompiler.class $(tasks)/unpack_bcel + $(JAVA) -cp $(CLASSPATH) org.xwt.mips.Compiler -outformat javasource $(compiler_flags) $($(notdir $*)_COMPILERFLAGS) $(subst /,.,$*) $< > build/$*.java + +build/%.class: build/%.java build/org/xwt/mips/Runtime.class + $(JAVAC) $(JAVAC_NODEBUG_FLAGS) -classpath build -d build $< +else + +build/%.class: build/%.mips build/org/xwt/mips/ClassFileCompiler.class $(tasks)/unpack_bcel + $(JAVA) -cp $(CLASSPATH) org.xwt.mips.Compiler -outformat class -outfile $@ $(compiler_flags) $($(notdir $*)_COMPILERFLAGS) $(subst /,.,$*) $< + + +endif + +# General Java Class compilation +build/%.class: src/%.java + $(JAVAC) -classpath build -d build $< + +clean: + rm -rf build/tests build/org/xwt/mips *.jar build/mips2java$(EXE_EXT) + +# +# env.sh +# +env.sh: Makefile $(tasks)/full_toolchain build/org/xwt/mips/Compiler.class $(tasks)/unpack_bcel + @rm -f "$@~" + @echo 'PATH="$(mips2java_root)/build:$(mips2java_root)/upstream/install/bin:$$PATH"; export PATH' >> $@~ + @echo 'CC=mips-unknown-elf-gcc; export CC' >> $@~ + @echo 'CXX=mips-unknown-elf-g++; export CXX' >> $@~ + @echo 'AS=mips-unknown-elf-as; export AS' >> $@~ + @echo 'LD=mips-unknown-elf-ar; export LD' >> $@~ + @echo 'RANLIB=mips-unknown-elf-ranlib; export RANLIB' >> $@~ + @echo 'CFLAGS="$(mips_optflags)"; export CFLAGS' >> $@~ + @echo 'CXXFLAGS="$(mips_optflags)"; export CXXFLAGS' >> $@~ + @echo 'LDFLAGS="$(MIPS_LDFLAGS)"; export LDFLAGS' >> $@~ + @echo 'CLASSPATH=$(mips2java_root)/build:$(mips2java_root)/upstream/build/bcel/bcel-5.1.jar:.; export CLASSPATH' >> $@~ + @mv "$@~" "$@" + @echo "$@ created successfully" + +# +# Runtime.jar +# + +runtime_util_classes = SeekableData SeekableByteArray SeekableFile SeekableInputStream +runtime_classes = Runtime Registers UsermodeConstants $(runtime_util_classes:%=util/%) +unixruntime_classes = $(runtime_classes) UnixRuntime + +runtime.jar: $(runtime_classes:%=build/org/xwt/mips/%.class) + cd build && jar cf ../$@ $(runtime_classes:%=org/xwt/mips/%*.class) + +unixruntime.jar: $(unixruntime_classes:%=build/org/xwt/mips/%.class) + cd build && jar cf ../$@ $(unixruntime_classes:%=org/xwt/mips/%*.class) + + + +# +# Tests +# These are simply here for convenience. They aren't required +# to build or run mips2java +# + +build/tests/Env.class: build/org/xwt/mips/Runtime.class build/org/xwt/mips/Interpreter.class + +# Generic Hello Worldish test +test: build/tests/Test.class + $(JAVA) -cp build tests.Test "arg 1" "arg 2" "arg 3" +inttest: build/tests/Test.mips build/org/xwt/mips/Interpreter.class + $(JAVA) -cp build org.xwt.mips.Interpreter build/tests/Test.mips "arg 1" "arg 2" "arg 3" +cxxtest: build/tests/CXXTest.class + $(JAVA) -cp build tests.CXXTest + +# CallTest +build/tests/CallTest.class: build/tests/Test.class +calltest: build/tests/CallTest.class + $(JAVA) -cp build tests.CallTest `date|perl -pe 's/\D+/ /g;'` `id -u` + +# FDTest +build/tests/FDTest.class: build/tests/Test.class +fdtest: build/tests/FDTest.class + $(JAVA) -cp build tests.FDTest + + +# Simple +Simple_LDFLAGS = -nostdlib +simpletest: build/tests/Simple.class + $(JAVA) -cp build tests.Simple + +# Paranoia +Paranoia_CFLAGS = "-Wno-error" +Paranoia_LDFLAGS = -lm +paranoiatest: build/tests/Paranoia.class + $(JAVA) -cp build tests.Paranoia + +# +# Freetype Stuff +# +FreeType_CFLAGS = -Iupstream/build/freetype/include +FreeType_LDFLAGS = -Lupstream/build/freetype/objs -lfreetype + +FreeTypeDemoHelper_CFLAGS = $(FreeType_CFLAGS) +FreeTypeDemoHelper_LDFLAGS = $(FreeType_LDFLAGS) +build/tests/FreeTypeDemoHelper.o: $(mips_objects) $(tasks)/build_freetype +build/tests/FreeTypeDemoHelper.mips: +build/tests/FreeTypeDemo.class: build/tests/FreeTypeDemoHelper.class + +FTBench_CFLAGS = $(FreeType_CFLAGS) +FTBench_LDFLAGS = $(FreeType_LDFLAGS) +build/tests/FTBench.o: $(tasks)/build_freetype + +# +# MSPack Stuff +# +MSPackHelper_CFLAGS = -Iupstream/build/libmspack/mspack +MSPackHelper_LDFLAGS = -Lupstream/build/libmspack/mspack -lmspack +build/tests/MSPackHelper.o: $(mips_objects) $(tasks)/build_libmspack +build/tests/MSPack.class: build/tests/MSPackHelper.class + +MSPackBench_CFLAGS = -Iupstream/build/libmspack/mspack +MSPackBench_LDFLAGS = -Lupstream/build/libmspack/mspack -lmspack +build/tests/MSPackBench.o: $(tasks)/build_libmspack + +# +# Echo +# +build/tests/Echo.class: build/tests/EchoHelper.class + +# +# Libjpeg +# +DJpeg_COMPILERFLAGS = -o onepage,pagesize=8m +build/tests/DJpeg.mips: $(mips_objects) $(tasks)/build_libjpeg + @mkdir -p `dirname $@` + cp upstream/build/libjpeg/djpeg $@ + +# +# Busybox +# +BusyBox_COMPILERFLAGS = -o unixruntime +build/tests/BusyBox.mips: $(mips_object) $(tasks)/build_busybox + @mkdir -p `dirname $@` + cp upstream/build/busybox/busybox $@ + +busyboxtest: build/tests/BusyBox.class + $(JAVA) -cp build tests.BusyBox ash + +# +# Boehm GC +# +build/tests/GCTest.mips: $(mips_objects) $(tasks)/build_boehmgc + @mkdir -p `dirname $@` + cp upstream/build/boehmgc/gctest $@ + +boehmgctest: build/tests/Env.class build/tests/GCTest.class + $(JAVA) -cp build tests.Env GC_PRINT_STATS=1 tests.GCTest + + +# +# Speed tests +# + +build/tests/SpeedTest.class: build/org/xwt/mips/Runtime.class + +tmp/thebride_1280.jpg: + @mkdir -p tmp + cd tmp && wget http://www.kill-bill.com/images/wallpaper/thebride_1280.jpg + +oldspeedtest: build/tests/DJpeg.class tmp/thebride_1280.jpg + bash -c "time $(JAVA) -cp build tests.DJpeg -targa -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg" + @echo "e90f6b915aee2fc0d2eb9fc60ace6203 tmp/thebride_1280.tga" | md5sum -c && echo "MD5 is OK" + +speedtest: build/tests/SpeedTest.class build/tests/DJpeg.class build/tests/FTBench.class tmp/thebride_1280.jpg build/tests/MSPackBench.class + @echo "Running DJpeg test..." + @$(JAVA) -cp build tests.SpeedTest tests.DJpeg 10 -targa -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg + @if [ -e tmp/mspack/Comic.TTF ]; then \ + echo "Running FTBench test..."; \ + $(JAVA) -cp build tests.SpeedTest tests.FTBench 10 tmp/mspack/Comic.TTF tmp/mspack/Comic.TTF.render; \ + else \ + echo "Run \"make check\" to get Arial.TTF for the FTBench test"; \ + fi + @if [ -e tmp/mspack/comic32.exe ]; then \ + echo "Running MSPackBench test..."; \ + cd tmp/mspack && $(JAVA) -cp ../../build tests.SpeedTest tests.MSPackBench 10 *32.exe; \ + else \ + echo "Run \"make check\" to get the MS True Type fonts for the MSPackBench test"; \ + fi + +intspeed: build/tests/DJpeg.mips build/org/xwt/mips/Interpreter.class tmp/thebride_1280.jpg + time $(JAVA) -cp build org.xwt.mips.Interpreter build/tests/DJpeg.mips -targa -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg + @echo "e90f6b915aee2fc0d2eb9fc60ace6203 tmp/thebride_1280.tga" | md5sum -c && echo "MD5 is OK" + +# +# Verification checks +# + +check: $(patsubst %,build/tests/%.class, FTBench MSPackBench DJpeg GCTest) tmp/thebride_1280.jpg + @/bin/bash ./src/tests/check.sh running_from_make + +compiletests: $(patsubst %,build/tests/%.class,FTBench MSPackBench DJpeg Test FreeTypeDemoHelper MSPackHelper EchoHelper BusyBox GCTest Fork) + @true + diff --git a/doc/COPYING b/doc/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/doc/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 0000000..e3eaaaf --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,59 @@ +January 11, 2003 + * [brian] Added Unistd.h as an interface so we can use its constants in + Runtime + * [brian] -o lessconstants option to compiler to emit all constants as + an addition of a field value and a small constant. This + prevents the classfile constant pool from overflowing on large + applications. This has a small performance impact. + * [brian] Added stubs for the rmdir syscall and a minimal implementation + of sysconf + * [brian] Emit data segments as a series of <32k strings to avoid + hitting classfile limits +January 10, 2003 + * [brian] The compiler now outputs data segments as Strings rather than + huge int arrays. + * [brian] Cleaned up Makefile and upstream/Makefile to separate the + required mips2java stuff from the tests. Ideally the tests + should be completelly separate from the main makefile but + keeping them integrated allows for better dependency checking + and faster builds. +January 8, 2003 + * Much thanks goes to Mohan Embar for discovering and fixing most + of the issues below. + * [brian] Updated Makefile to allow bulding with gcj + (make JAVAC="gcj -C" JAVA="gij") + * [brian] Updated Runtime.java to silently ignore SecurityExceptions + thrown from System.getProperty() + * [brian] Compiler now uses a PrintWriter for output rather than + PrintStream and properly closes the file on exit + * [brian] Made the htojava script a bourne shell script rather than a + perl script to remove the dependency on perl. +December 29, 2003 + * [brian] Changed build process to use -ffunction-sections, + -fdata-sections, and --gc-sections + * [brian] Update support.s to use function sections + * [brian] Make the interpreter report the pc/sourceline of + exceptions. + * [brian] Remove stdio calls from FreeTypeHelper + * [brian] Added gcc patch to fix -fdata-sections bug + * [brian] Added freetype patch to avoid stdio +December 2, 2003 + * [brian] Cleaned up a bunch of //FEATUREs and //FIXMEs. No major + changes, just cleanup. +November 30, 2003 + * [brian] Added crude support for O_APPEND and O_TRUNC + +November 29, 2003 + * [brian] Moved all sources under org/xwt/mips - modified Makefiles + accordingly. + * [brian] Added org.xwt.mips.util tree containing SeekableData, + SeekableByteArray, SeekableFile, and SeekableInputStream. + * [brian] Made ELF.java use SeekableData rather than RandomAccessFile + * [brian] Made Runtime.java use org.xwt.mips.util.Seekable* for most + file operations. + * [brian] Added construtors to Interpreter.java that accept an InputStream + or SeekableData. + * [brian] Added support for the /dev/fd/n namespace and /dev/{null,zero} + * [brian] Added test/FDTest.java example and updated tests/Test.c + * [brian] Fixed absolute pathame bug on Win32 + \ No newline at end of file diff --git a/src/org/xwt/mips/ClassFileCompiler.java b/src/org/xwt/mips/ClassFileCompiler.java new file mode 100644 index 0000000..6619777 --- /dev/null +++ b/src/org/xwt/mips/ClassFileCompiler.java @@ -0,0 +1,2160 @@ +package org.xwt.mips; + +import java.io.*; +import org.xwt.mips.util.*; + +import org.apache.bcel.generic.*; + +// FEATURE: Use BCEL to do peephole optimization +// FEATURE: Special mode to support single-precision only - regs are floats not ints + +/* FEATURE: Span large binaries across several classfiles + * We should be able to do this with no performance penalty + * Every method in the inner classes is static and takes the main class as an arg + * This makes them look just like methods in the main class because arg1 gets loaded into + * local register 0 + */ + +/* FEATURE: smarter with local regs + * Be even smarter with the use of local registers. We need to only load fields into + * local regs when they are actually used and only write to fields if the regs could have + * changed. This should allow us to put more regs in local vars. Right now putting all used + * regs local vars makes code like this slower. + * + * void work(int a, int b) { + * if(a == b) { + * fast path + * return; + * } + * real work + * } + * Because all the regs used in "real work" are loaded/restored even for fast path + */ + + +public class ClassFileCompiler extends Compiler implements org.apache.bcel.Constants { + /** The stream to write the compiled output to */ + private OutputStream os; + private PrintStream warn = System.err; + + private ClassGen cl; + private ConstantPoolGen cp; + private InstructionList clinitExtras = new InstructionList(); + private InstructionList initExtras = new InstructionList(); + private InstructionFactory fac; + + // Handy wrappers around the BCEL functions + private InstructionList insnList; + private void selectMethod(MethodGen m) { insnList = m.getInstructionList(); } + private void selectList(InstructionList l) { insnList = l; } + private InstructionHandle a(Instruction i) { return insnList.append(i); } + private BranchHandle a(BranchInstruction i) { return insnList.append(i); } + private InstructionHandle a(InstructionList l) { return insnList.append(l); } + private InstructionHandle a(CompoundInstruction c) { return insnList.append(c); } + + // This works around a bug in InstructionList + // FEATURE: fix this in bcel, send them a patch, etc + private static class FixedInstructionList extends InstructionList { + public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) { + InstructionHandle extra = target != null && target == getEnd() ? append(InstructionConstants.NOP) : null; + super.move(start,end,target); + if(extra != null) try { delete(extra); } catch (TargetLostException e) { /* won't happen */ } + } + } + + private MethodGen newMethod(int flags, Type ret, Type[] args, String name) { + return new MethodGen(flags,ret,args,null,name,fullClassName,new FixedInstructionList(),cp); + } + + public ClassFileCompiler(String path, String className, OutputStream os) throws IOException { this(new SeekableFile(path),className,os); } + public ClassFileCompiler(SeekableData binary, String className, OutputStream os) throws IOException { + super(binary,className); + this.os = os; + } + + public void setWarnWriter(PrintStream warn) { this.warn = warn; } + + protected void _go() throws Exn, IOException { + if(lessConstants) throw new Exn("ClassFileCompiler doesn't support -o lessconstants"); + if(!pruneCases) throw new Exn("-o prunecases MUST be enabled for ClassFileCompiler"); + + // Class + cl = new ClassGen(fullClassName,runtimeClass,source,ACC_SUPER|ACC_PUBLIC,null); + cp = cl.getConstantPool(); + fac = new InstructionFactory(cl,cp); + + // Fields + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"pc",cp).getField()); + for(int i=1;i<32;i++) + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"r"+i,cp).getField()); + for(int i=0;i<32;i++) + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"f"+i,cp).getField()); + + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"hi",cp).getField()); + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"lo",cp).getField()); + cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"fcsr",cp).getField()); + + if(onePage) { + cl.addField(new FieldGen(ACC_PRIVATE|ACC_FINAL,new ArrayType(Type.INT,1),"page",cp).getField()); + + selectList(initExtras); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.DUP); + a(fac.createFieldAccess(fullClassName,"readPages",new ArrayType(Type.INT, 2), GETFIELD)); + pushConst(0); + a(InstructionConstants.AALOAD); + a(fac.createFieldAccess(fullClassName,"page",new ArrayType(Type.INT,1), PUTFIELD)); + } + + if(supportCall) + cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,Type.getType("L"+hashClass.replace('.','/')+";"),"symbols",cp).getField()); + + int highestAddr = 0; + + for(int i=0;i>> methodShift; + int end = ((text.addr + text.size) >>> methodShift) + 1; + + // This data is redundant but BCEL wants it + int[] matches = new int[end-beg]; + for(int i=beg;i",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"r2",Type.INT, GETFIELD)); + a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); + a(new PUSH(cp," pc:")); + a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.STRING},INVOKEVIRTUAL)); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); + a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); + a(new PUSH(cp,')')); + a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.CHAR},INVOKEVIRTUAL)); + a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL)); + a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ATHROW); + + stateCheck.setTarget(a(InstructionConstants.RETURN)); + + tramp.setMaxStack(); + tramp.setMaxLocals(); + try { + cl.addMethod(tramp.getMethod()); + } catch(ClassGenException e) { + e.printStackTrace(warn); + throw new Exn("Generation of the trampoline method failed. Try increasing maxInsnPerMethod"); + } + + MethodGen init = newMethod(ACC_PUBLIC,Type.VOID, Type.NO_ARGS, ""); + selectMethod(init); + // Constructor + a(InstructionConstants.ALOAD_0); + pushConst(pageSize); + pushConst(totalPages); + pushConst(fastMem ? 0 : 1); + a(fac.createInvoke(runtimeClass,"",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN},INVOKESPECIAL)); + a(InstructionConstants.ALOAD_0); + pushConst(gp.addr); + a(fac.createFieldAccess(fullClassName,"gp",Type.INT, PUTFIELD)); + + a(InstructionConstants.ALOAD_0); + pushConst(elf.header.entry); + a(fac.createFieldAccess(fullClassName,"entryPoint",Type.INT, PUTFIELD)); + + a(InstructionConstants.ALOAD_0); + pushConst(onePage ? ((highestAddr+4095)&~4095) : ((highestAddr+pageSize-1)&~(pageSize-1))); + a(fac.createFieldAccess(fullClassName,"brkAddr",Type.INT, PUTFIELD)); + + if(userInfo != null) { + a(InstructionConstants.ALOAD_0); + pushConst(userInfo.addr); + a(fac.createFieldAccess(fullClassName,"userInfoBase",Type.INT, PUTFIELD)); + a(InstructionConstants.ALOAD_0); + pushConst(userInfo.size); + a(fac.createFieldAccess(fullClassName,"userInfoSize",Type.INT, PUTFIELD)); + } + a(initExtras); + a(InstructionConstants.ALOAD_0); + pushConst(Runtime.INITIALIZED); + a(fac.createFieldAccess(fullClassName,"state",Type.INT, PUTFIELD)); + a(InstructionConstants.RETURN); + init.setMaxLocals(); + init.setMaxStack(); + cl.addMethod(init.getMethod()); + + MethodGen clinit = newMethod(ACC_PRIVATE|ACC_STATIC,Type.VOID, Type.NO_ARGS, ""); + selectMethod(clinit); + a(clinitExtras); + + if(supportCall) { + a(fac.createNew(hashClass)); + a(InstructionConstants.DUP); + a(InstructionConstants.DUP); + a(fac.createInvoke(hashClass,"",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); + a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), PUTSTATIC)); + ELF.Symbol[] symbols = elf.getSymtab().symbols; + for(int i=0;i",Type.VOID,new Type[]{Type.INT},INVOKESPECIAL)); + a(fac.createInvoke(hashClass,"put",Type.OBJECT,new Type[]{Type.OBJECT,Type.OBJECT},INVOKEVIRTUAL)); + a(InstructionConstants.POP); + } + } + a(InstructionConstants.POP); + } + + a(InstructionConstants.RETURN); + clinit.setMaxLocals(); + clinit.setMaxStack(); + cl.addMethod(clinit.getMethod()); + + if(supportCall) { + MethodGen lookupSymbol = newMethod(ACC_PROTECTED,Type.INT,new Type[]{Type.STRING},"lookupSymbol"); + selectMethod(lookupSymbol); + a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), GETSTATIC)); + a(InstructionConstants.ALOAD_1); + a(fac.createInvoke(hashClass,"get",Type.OBJECT,new Type[]{Type.OBJECT},INVOKEVIRTUAL)); + a(InstructionConstants.DUP); + BranchHandle bh = a(InstructionFactory.createBranchInstruction(IFNULL,null)); + a(fac.createCheckCast(new ObjectType("java.lang.Integer"))); + a(fac.createInvoke("java.lang.Integer","intValue",Type.INT,Type.NO_ARGS,INVOKEVIRTUAL)); + a(InstructionConstants.IRETURN); + bh.setTarget(a(InstructionConstants.ICONST_M1)); + a(InstructionConstants.IRETURN); + lookupSymbol.setMaxLocals(); + lookupSymbol.setMaxStack(); + cl.addMethod(lookupSymbol.getMethod()); + } + + MethodGen setCPUState = newMethod(ACC_PROTECTED,Type.VOID,new Type[]{Type.getType("Lorg/xwt/mips/Runtime$CPUState;")},"setCPUState"); + selectMethod(setCPUState); + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD)); + a(InstructionConstants.ASTORE_2); + for(int i=1;i<32;i++) { + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_2); + pushConst(i); + a(InstructionConstants.IALOAD); + a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, PUTFIELD)); + } + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD)); + a(InstructionConstants.ASTORE_2); + for(int i=0;i<32;i++) { + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_2); + pushConst(i); + a(InstructionConstants.IALOAD); + a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, PUTFIELD)); + } + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","hi",Type.INT,GETFIELD)); + a(fac.createFieldAccess(fullClassName,"hi",Type.INT, PUTFIELD)); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","lo",Type.INT,GETFIELD)); + a(fac.createFieldAccess(fullClassName,"lo",Type.INT, PUTFIELD)); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","fcsr",Type.INT,GETFIELD)); + a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, PUTFIELD)); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","pc",Type.INT,GETFIELD)); + a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD)); + a(InstructionConstants.RETURN); + setCPUState.setMaxLocals(); + setCPUState.setMaxStack(); + cl.addMethod(setCPUState.getMethod()); + + MethodGen getCPUState = newMethod(ACC_PROTECTED,Type.getType("Lorg/xwt/mips/Runtime$CPUState;"),Type.NO_ARGS,"getCPUState"); + selectMethod(getCPUState); + a(fac.createNew("org.xwt.mips.Runtime$CPUState")); + a(InstructionConstants.DUP); + a(fac.createInvoke("org.xwt.mips.Runtime$CPUState","",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); + a(InstructionConstants.ASTORE_1); + + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD)); + a(InstructionConstants.ASTORE_2); + for(int i=1;i<32;i++) { + a(InstructionConstants.ALOAD_2); + pushConst(i); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, GETFIELD)); + a(InstructionConstants.IASTORE); + } + + a(InstructionConstants.ALOAD_1); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD)); + a(InstructionConstants.ASTORE_2); + for(int i=0;i<32;i++) { + a(InstructionConstants.ALOAD_2); + pushConst(i); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, GETFIELD)); + a(InstructionConstants.IASTORE); + } + a(InstructionConstants.ALOAD_1); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"hi",Type.INT, GETFIELD)); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","hi",Type.INT,PUTFIELD)); + a(InstructionConstants.ALOAD_1); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"lo",Type.INT, GETFIELD)); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","lo",Type.INT,PUTFIELD)); + a(InstructionConstants.ALOAD_1); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, GETFIELD)); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","fcsr",Type.INT,PUTFIELD)); + a(InstructionConstants.ALOAD_1); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); + a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","pc",Type.INT,PUTFIELD)); + + a(InstructionConstants.ALOAD_1); + a(InstructionConstants.ARETURN); + getCPUState.setMaxLocals(); + getCPUState.setMaxStack(); + cl.addMethod(getCPUState.getMethod()); + + + MethodGen execute = newMethod(ACC_PROTECTED,Type.VOID,Type.NO_ARGS,"_execute"); + selectMethod(execute); + a(InstructionConstants.ALOAD_0); + a(fac.createInvoke(fullClassName,"trampoline",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); + a(InstructionConstants.RETURN); + execute.setMaxLocals(); + execute.setMaxStack(); + cl.addMethod(execute.getMethod()); + + + MethodGen main = newMethod(ACC_STATIC|ACC_PUBLIC,Type.VOID,new Type[]{new ArrayType(Type.STRING,1)},"main"); + selectMethod(main); + a(fac.createNew(fullClassName)); + a(InstructionConstants.DUP); + a(fac.createInvoke(fullClassName,"",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); + a(new PUSH(cp,fullClassName)); + a(InstructionConstants.ALOAD_0); + a(fac.createInvoke(fullClassName,"run",Type.INT,new Type[]{Type.STRING,new ArrayType(Type.STRING,1)},INVOKEVIRTUAL)); + a(fac.createInvoke("java.lang.System","exit",Type.VOID,new Type[]{Type.INT},INVOKESTATIC)); + a(InstructionConstants.RETURN); + main.setMaxLocals(); + main.setMaxStack(); + cl.addMethod(main.getMethod()); + + cl.getJavaClass().dump(os); + } + + private static int initDataCount; + private void emitData(int addr, DataInputStream dis, int size, boolean readOnly) throws Exn,IOException { + if((addr&3)!=0 || (size&3)!=0) throw new Exn("Data section on weird boundaries"); + int last = addr + size; + while(addr < last) { + int segSize = Math.min(size,28000); // must be a multiple of 56 + StringBuffer sb = new StringBuffer(); + for(int i=0;i>>(7*(7-j)))&0x7f)); + } + String fieldname = "_data" + (++initDataCount); + cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,new ArrayType(Type.INT,1),fieldname,cp).getField()); + + selectList(clinitExtras); + a(new PUSH(cp,sb.toString())); + a(new PUSH(cp,segSize/4)); + a(fac.createInvoke("org.xwt.mips.Runtime","decodeData",new ArrayType(Type.INT,1),new Type[]{Type.STRING,Type.INT},INVOKESTATIC)); + a(fac.createPutStatic(fullClassName,fieldname,new ArrayType(Type.INT,1))); + + selectList(initExtras); + a(InstructionConstants.ALOAD_0); + a(fac.createGetStatic(fullClassName,fieldname,new ArrayType(Type.INT,1))); + a(new PUSH(cp,addr)); + a(new PUSH(cp,readOnly)); + a(fac.createInvoke(fullClassName,"initPages",Type.VOID,new Type[]{new ArrayType(Type.INT,1),Type.INT,Type.BOOLEAN},INVOKEVIRTUAL)); + + addr += segSize; + size -= segSize; + } + dis.close(); + } + + private void emitBSS(int addr, int size) throws Exn { + if((addr&3)!=0) throw new Exn("BSS section on weird boundaries"); + size = (size+3)&~3; + int count = size/4; + selectList(initExtras); + a(InstructionConstants.ALOAD_0); + a(new PUSH(cp,addr)); + a(new PUSH(cp,count)); + a(fac.createInvoke(fullClassName,"clearPages",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL)); + } + + // method state info + private boolean textDone; + private int startOfMethod = 0; + private int endOfMethod = 0; + private boolean unreachable = false; + private InstructionHandle[] jumpHandles; + private InstructionHandle defaultHandle; + private InstructionHandle returnHandle; + private InstructionHandle realStart; + private MethodGen curMethod; + + private boolean jumpable(int addr) { return jumpableAddresses.contains(new Integer(addr)); } + + private void emitText(int addr, DataInputStream dis, int size) throws Exn,IOException { + if(textDone) throw new Exn("Multiple text segments"); + textDone = true; + + if((addr&3)!=0 || (size&3)!=0) throw new Exn("Section on weird boundaries"); + int count = size/4; + int insn,nextInsn=-1; + boolean skipNext = true; + + for(int i=0;i= endOfMethod) { endMethod(addr); startMethod(addr); } + if(jumpHandles[(addr-startOfMethod)/4] != null) { + // Move the fake jump target to the current location + insnList.move(jumpHandles[(addr-startOfMethod)/4],insnList.getEnd()); + unreachable = false; + } else if(unreachable) { + continue; + } + try { + skipNext = emitInstruction(addr,insn,nextInsn); + } catch(RuntimeException e) { + warn.println("Exception at " + toHex(addr)); + throw e; + } + if(skipNext) { addr+=4; i++; } + } + endMethod(0); + dis.close(); + } + + private void startMethod(int first) { + startOfMethod = first & methodMask; + endOfMethod = startOfMethod + maxBytesPerMethod; + curMethod = newMethod(ACC_PRIVATE,Type.VOID,Type.NO_ARGS,"run_" + toHex(startOfMethod)); + selectMethod(curMethod); + + int[] buf = new int[maxBytesPerMethod/4]; + jumpHandles = new InstructionHandle[maxBytesPerMethod/4]; + int n=0; + for(int addr=first;addr",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); + a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); + a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL)); + a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ATHROW); + } else { + a(fac.createNew("org.xwt.mips.Runtime$ExecutionException")); + a(InstructionConstants.DUP); + a(new PUSH(cp,"Jumped to invalid address")); + a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ATHROW); + } + + if(insnList.getStart() != realStart) { + System.err.println(insnList); + throw new Error("A jumpHandle wasn't moved into place"); + } + + curMethod.removeNOPs(); + curMethod.setMaxLocals(); + curMethod.setMaxStack(); + + cl.addMethod(curMethod.getMethod()); + + endOfMethod = startOfMethod = 0; + } + + + private void leaveMethod() { + a(InstructionFactory.createBranchInstruction(GOTO,returnHandle)); + } + + private void branch(int pc, int target) { + if((pc&methodMask) == (target&methodMask)) { + a(InstructionFactory.createBranchInstruction(GOTO,jumpHandles[(target-startOfMethod)/4])); + } else { + preSetPC(); + pushConst(target); + setPC(); + leaveMethod(); + } + } + + // This assumes everything needed by ifInsn is already on the stack + private boolean doIfInstruction(short op, int pc, int target, int nextInsn) throws Exn { + emitInstruction(-1,nextInsn,-1); // delay slot + BranchHandle h; + IfInstruction ifInsn = (IfInstruction) InstructionFactory.createBranchInstruction(op,null); + if((target&methodMask) == (pc&methodMask)) { + h = a(ifInsn); + h.setTarget(jumpHandles[(target-startOfMethod)/4]); + } else { + h = a(ifInsn.negate()); + branch(pc,target); + h.setTarget(a(InstructionConstants.NOP)); + } + if(!jumpable(pc+4)) return true; // done - skip it + + //System.err.println("Delay slot is jumpable - This code is untested + " + toHex(nextInsn)); + if(pc+4==endOfMethod) { + // the delay slot is at the start of the next method + jumpableAddresses.add(new Integer(pc+8)); // make the 2nd insn of the next method jumpable + branch(pc,pc+8); // jump over it + //System.err.println("delay slot: " + toHex(pc+8)); + unreachable = true; + return false; // we still need to output it + } else { + //System.err.println("jumped over delay slot: " + toHex(pc+4)); + // add another copy and jump over + h = a(InstructionFactory.createBranchInstruction(GOTO,null)); + insnList.move(jumpHandles[(pc+4-startOfMethod)/4],insnList.getEnd()); + emitInstruction(-1,nextInsn,-1); // delay slot + h.setTarget(a(InstructionConstants.NOP)); + return true; + } + } + + private boolean emitInstruction(int pc, int insn, int nextInsn) throws Exn { + if(insn == -1) throw new Exn("insn is -1"); + + int op = (insn >>> 26) & 0xff; // bits 26-31 + int rs = (insn >>> 21) & 0x1f; // bits 21-25 + int rt = (insn >>> 16) & 0x1f; // bits 16-20 + int ft = (insn >>> 16) & 0x1f; + int rd = (insn >>> 11) & 0x1f; // bits 11-15 + int fs = (insn >>> 11) & 0x1f; + int shamt = (insn >>> 6) & 0x1f; // bits 6-10 + int fd = (insn >>> 6) & 0x1f; + int subcode = insn & 0x3f; // bits 0-5 + int breakCode = (insn >>> 6) & 0xfffff; // bits 6-20 + + int jumpTarget = (insn & 0x03ffffff); // bits 0-25 + int unsignedImmediate = insn & 0xffff; + int signedImmediate = (insn << 16) >> 16; + int branchTarget = signedImmediate; + + // temporaries + BranchHandle b1,b2; + + switch(op) { + case 0: { + switch(subcode) { + case 0: // SLL + if(insn == 0) break; + preSetReg(R+rd); + pushRegWZ(R+rt); + pushConst(shamt); + a(InstructionConstants.ISHL); + setReg(); + break; + case 2: // SRL + preSetReg(R+rd); + pushRegWZ(R+rt); + pushConst(shamt); + a(InstructionConstants.IUSHR); + setReg(); + break; + case 3: // SRA + preSetReg(R+rd); + pushRegWZ(R+rt); + pushConst(shamt); + a(InstructionConstants.ISHR); + setReg(); + break; + case 4: // SLLV + preSetReg(R+rd); + pushRegWZ(R+rt); + pushRegWZ(R+rs); + a(InstructionConstants.ISHL); + setReg(); + break; + case 6: // SRLV + preSetReg(R+rd); + pushRegWZ(R+rt); + pushRegWZ(R+rs); + a(InstructionConstants.IUSHR); + setReg(); + break; + case 7: // SRAV + preSetReg(R+rd); + pushRegWZ(R+rt); + pushRegWZ(R+rs); + a(InstructionConstants.ISHR); + setReg(); + break; + case 8: // JR + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + preSetPC(); + pushRegWZ(R+rs); + setPC(); + leaveMethod(); + unreachable = true; + break; + case 9: // JALR + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + preSetPC(); + pushRegWZ(R+rs); + setPC(); + + preSetReg(R+RA); + pushConst(pc+8); + setReg(); + leaveMethod(); + unreachable = true; + break; + case 12: // SYSCALL + preSetPC(); + pushConst(pc); + setPC(); + + restoreChangedRegs(); + + preSetReg(R+V0); + a(InstructionConstants.ALOAD_0); + pushRegZ(R+V0); + pushRegZ(R+A0); + pushRegZ(R+A1); + pushRegZ(R+A2); + pushRegZ(R+A3); + a(fac.createInvoke(fullClassName,"syscall",Type.INT,new Type[]{Type.INT,Type.INT,Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL)); + setReg(); + + a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,"state",Type.INT, GETFIELD)); + pushConst(Runtime.RUNNING); + b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPEQ,null)); + preSetPC(); + pushConst(pc+4); + setPC(); + leaveMethod(); + b1.setTarget(a(InstructionConstants.NOP)); + + break; + case 13: // BREAK + a(fac.createNew("org.xwt.mips.Runtime$ExecutionException")); + a(InstructionConstants.DUP); + a(new PUSH(cp,"BREAK Code " + toHex(breakCode))); + a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); + a(InstructionConstants.ATHROW); + unreachable = true; + break; + case 16: // MFHI + preSetReg(R+rd); + pushReg(HI); + setReg(); + break; + case 17: // MTHI + preSetReg(HI); + pushRegZ(R+rs); + setReg(); + break; + case 18: // MFLO + preSetReg(R+rd); + pushReg(LO); + setReg(); + break; + case 19: // MTLO + preSetReg(LO); + pushRegZ(R+rs); + setReg(); + break; + case 24: // MULT + pushRegWZ(R+rs); + a(InstructionConstants.I2L); + pushRegWZ(R+rt); + a(InstructionConstants.I2L); + a(InstructionConstants.LMUL); + a(InstructionConstants.DUP2); + + a(InstructionConstants.L2I); + if(preSetReg(LO)) + a(InstructionConstants.SWAP); + setReg(); + + pushConst(32); + a(InstructionConstants.LUSHR); + a(InstructionConstants.L2I); + if(preSetReg(HI)) + a(InstructionConstants.SWAP); + setReg(); + + break; + case 25: // MULTU + pushRegWZ(R+rs); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + pushRegWZ(R+rt); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + a(InstructionConstants.LMUL); + a(InstructionConstants.DUP2); + + a(InstructionConstants.L2I); + if(preSetReg(LO)) + a(InstructionConstants.SWAP); + setReg(); + + pushConst(32); + a(InstructionConstants.LUSHR); + a(InstructionConstants.L2I); + if(preSetReg(HI)) + a(InstructionConstants.SWAP); + setReg(); + + break; + case 26: // DIV + pushRegWZ(R+rs); + pushRegWZ(R+rt); + a(InstructionConstants.DUP2); + + a(InstructionConstants.IDIV); + if(preSetReg(LO)) + a(InstructionConstants.SWAP); + setReg(); + + a(InstructionConstants.IREM); + if(preSetReg(HI)) + a(InstructionConstants.SWAP); + setReg(); + + break; + case 27: { // DIVU + pushRegWZ(R+rt); + a(InstructionConstants.DUP); + setTmp(); + b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null)); + + pushRegWZ(R+rs); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + a(InstructionConstants.DUP2); + pushTmp(); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + + a(InstructionConstants.LAND); + a(InstructionConstants.DUP2_X2); + a(InstructionConstants.LDIV); + + a(InstructionConstants.L2I); + if(preSetReg(LO)) + a(InstructionConstants.SWAP); + setReg(); + + a(InstructionConstants.LREM); + a(InstructionConstants.L2I); + if(preSetReg(HI)) + a(InstructionConstants.SWAP); + setReg(); + + b1.setTarget(a(InstructionConstants.NOP)); + + break; + } + case 32: // ADD + throw new Exn("ADD (add with oveflow trap) not suported"); + case 33: // ADDU + preSetReg(R+rd); + if(rt != 0 && rs != 0) { + pushReg(R+rs); + pushReg(R+rt); + a(InstructionConstants.IADD); + } else if(rs != 0) { + pushReg(R+rs); + } else { + pushRegZ(R+rt); + } + setReg(); + break; + case 34: // SUB + throw new Exn("SUB (add with oveflow trap) not suported"); + case 35: // SUBU + preSetReg(R+rd); + if(rt != 0 && rs != 0) { + pushReg(R+rs); + pushReg(R+rt); + a(InstructionConstants.ISUB); + } else if(rt != 0) { + pushReg(R+rt); + a(InstructionConstants.INEG); + } else { + pushRegZ(R+rs); + } + setReg(); + break; + case 36: // AND + preSetReg(R+rd); + pushRegWZ(R+rs); + pushRegWZ(R+rt); + a(InstructionConstants.IAND); + setReg(); + break; + case 37: // OR + preSetReg(R+rd); + pushRegWZ(R+rs); + pushRegWZ(R+rt); + a(InstructionConstants.IOR); + setReg(); + break; + case 38: // XOR + preSetReg(R+rd); + pushRegWZ(R+rs); + pushRegWZ(R+rt); + a(InstructionConstants.IXOR); + setReg(); + break; + case 39: // NOR + preSetReg(R+rd); + if(rs != 0 || rt != 0) { + if(rs != 0 && rt != 0) { + pushReg(R+rs); + pushReg(R+rt); + a(InstructionConstants.IOR); + } else if(rs != 0) { + pushReg(R+rs); + } else { + pushReg(R+rt); + } + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + } else { + pushConst(-1); + } + setReg(); + break; + case 42: // SLT + preSetReg(R+rd); + if(rs != rt) { + pushRegZ(R+rs); + pushRegZ(R+rt); + b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null)); + a(InstructionConstants.ICONST_0); + b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + b1.setTarget(a(InstructionConstants.ICONST_1)); + b2.setTarget(a(InstructionConstants.NOP)); + } else { + pushConst(0); + } + setReg(); + break; + case 43: // SLTU + preSetReg(R+rd); + if(rs != rt) { + if(rs != 0) { + pushReg(R+rs); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + pushReg(R+rt); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + a(InstructionConstants.LCMP); + b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); + } else { + pushReg(R+rt); + b1 = a(InstructionFactory.createBranchInstruction(IFNE,null)); + } + a(InstructionConstants.ICONST_0); + b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + b1.setTarget(a(InstructionConstants.ICONST_1)); + b2.setTarget(a(InstructionConstants.NOP)); + } else { + pushConst(0); + } + setReg(); + break; + default: + throw new RuntimeException("Illegal instruction 0/" + subcode); + } + break; + } + case 1: { + switch(rt) { + case 0: // BLTZ + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + return doIfInstruction(IFLT,pc,pc+branchTarget*4+4,nextInsn); + case 1: // BGEZ + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + return doIfInstruction(IFGE,pc,pc+branchTarget*4+4,nextInsn); + case 16: // BLTZAL + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + b1 = a(InstructionFactory.createBranchInstruction(IFGE,null)); + emitInstruction(-1,nextInsn,-1); + preSetReg(R+RA); + pushConst(pc+8); + setReg(); + branch(pc,pc+branchTarget*4+4); + b1.setTarget(a(InstructionConstants.NOP)); + break; + case 17: // BGEZAL + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + b1 = null; + if(rs != 0) { // r0 is always >= 0 + pushRegWZ(R+rs); + b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); + } + emitInstruction(-1,nextInsn,-1); + preSetReg(R+RA); + pushConst(pc+8); + setReg(); + branch(pc,pc+branchTarget*4+4); + if(b1 != null) b1.setTarget(a(InstructionConstants.NOP)); + if(b1 == null) unreachable = true; + break; + default: + throw new RuntimeException("Illegal Instruction 1/" + rt); + } + break; + } + case 2: { // J + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + branch(pc,(pc&0xf0000000)|(jumpTarget << 2)); + unreachable = true; + break; + } + case 3: { // JAL + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + int target = (pc&0xf0000000)|(jumpTarget << 2); + emitInstruction(-1,nextInsn,-1); + if(optimizedMemcpy && (target == memcpy || target == memset)) { + a(InstructionConstants.ALOAD_0); + pushRegZ(R+4); + pushRegZ(R+5); + pushRegZ(R+6); + a(fac.createInvoke(fullClassName,target==memcpy ? "memcpy" : "memset", Type.VOID, new Type[]{Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL)); + preSetReg(R+2); + pushReg(R+4); + setReg(); + branch(pc,pc+8); + } else { + preSetReg(R+RA); + pushConst(pc+8); + setReg(); + branch(pc, target); + } + unreachable = true; + break; + } + case 4: // BEQ + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + if(rs == rt) { + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + unreachable = true; + } else if(rs == 0 || rt == 0) { + pushReg(rt == 0 ? R+rs : R+rt); + return doIfInstruction(IFEQ,pc,pc+branchTarget*4+4,nextInsn); + } else { + pushReg(R+rs); + pushReg(R+rt); + return doIfInstruction(IF_ICMPEQ,pc,pc+branchTarget*4+4,nextInsn); + } + break; + case 5: // BNE + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + if(rt == 0) { + return doIfInstruction(IFNE,pc,pc+branchTarget*4+4,nextInsn); + } else { + pushReg(R+rt); + return doIfInstruction(IF_ICMPNE,pc,pc+branchTarget*4+4,nextInsn); + } + case 6: //BLEZ + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + return doIfInstruction(IFLE,pc,pc+branchTarget*4+4,nextInsn); + case 7: //BGTZ + if(pc == -1) throw new Exn("pc modifying insn in delay slot"); + pushRegWZ(R+rs); + return doIfInstruction(IFGT,pc,pc+branchTarget*4+4,nextInsn); + case 8: // ADDI + throw new Exn("ADDI (add immediate with oveflow trap) not suported"); + case 9: // ADDIU + preSetReg(R+rt); + addiu(rs,signedImmediate); + setReg(); + break; + case 10: // SLTI + preSetReg(R+rt); + pushRegWZ(R+rs); + pushConst(signedImmediate); + b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null)); + a(InstructionConstants.ICONST_0); + b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + b1.setTarget(a(InstructionConstants.ICONST_1)); + b2.setTarget(a(InstructionConstants.NOP)); + setReg(); + break; + case 11: // SLTIU + preSetReg(R+rt); + pushRegWZ(R+rs); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + pushConst((long)unsignedImmediate); + a(InstructionConstants.LCMP); + + b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); + a(InstructionConstants.ICONST_0); + b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + b1.setTarget(a(InstructionConstants.ICONST_1)); + b2.setTarget(a(InstructionConstants.NOP)); + + setReg(); + break; + case 12: // ANDI + preSetReg(R+rt); + pushRegWZ(R+rs); + pushConst(unsignedImmediate); + a(InstructionConstants.IAND); + setReg(); + break; + case 13: // ORI + preSetReg(R+rt); + if(rs != 0 && unsignedImmediate != 0) { + pushReg(R+rs); + pushConst(unsignedImmediate); + a(InstructionConstants.IOR); + } else if(rs != 0){ + pushReg(R+rs); + } else { + pushConst(unsignedImmediate); + } + setReg(); + break; + case 14: // XORI + preSetReg(R+rt); + pushRegWZ(R+rs); + pushConst(unsignedImmediate); + a(InstructionConstants.IXOR); + setReg(); + break; + case 15: // LUI + preSetReg(R+rt); + pushConst(unsignedImmediate << 16); + setReg(); + break; + case 16: + throw new Exn("TLB/Exception support not implemented"); + case 17: { // FPU + switch(rs) { + case 0: // MFC.1 + preSetReg(R+rt); + pushReg(F+rd); + setReg(); + break; + case 2: // CFC.1 + if(fs != 31) throw new Exn("FCR " + fs + " unavailable"); + preSetReg(R+rt); + pushReg(FCSR); + setReg(); + break; + case 4: // MTC.1 + preSetReg(F+rd); + if(rt != 0) + pushReg(R+rt); + else + pushConst(0); + setReg(); + break; + case 6: // CTC.1 + if(fs != 31) throw new Exn("FCR " + fs + " unavailable"); + preSetReg(FCSR); + pushReg(R+rt); + setReg(); + break; + case 8: {// BC1F, BC1T + pushReg(FCSR); + pushConst(0x800000); + a(InstructionConstants.IAND); + return doIfInstruction(((insn>>>16)&1) == 0 ? IFEQ : IFNE,pc,pc+branchTarget*4+4,nextInsn); + } + case 16: + case 17: + { // Single/Double math + boolean d = rs == 17; + switch(subcode) { + case 0: // ADD.X + preSetDouble(F+fd,d); + pushDouble(F+fs,d); + pushDouble(F+ft,d); + a(d ? InstructionConstants.DADD : InstructionConstants.FADD); + setDouble(d); + break; + case 1: // SUB.X + preSetDouble(F+fd,d); + pushDouble(F+fs,d); + pushDouble(F+ft,d); + a(d ? InstructionConstants.DSUB : InstructionConstants.FSUB); + setDouble(d); + break; + case 2: // MUL.X + preSetDouble(F+fd,d); + pushDouble(F+fs,d); + pushDouble(F+ft,d); + a(d ? InstructionConstants.DMUL : InstructionConstants.FMUL); + setDouble(d); + break; + case 3: // DIV.X + preSetDouble(F+fd,d); + pushDouble(F+fs,d); + pushDouble(F+ft,d); + a(d ? InstructionConstants.DDIV : InstructionConstants.FDIV); + setDouble(d); + break; + case 5: // ABS.X + preSetDouble(F+fd,d); + // NOTE: We can't use fneg/dneg here since they'll turn +0.0 into -0.0 + + pushDouble(F+fs,d); + a(d ? InstructionConstants.DUP2 : InstructionConstants.DUP); + a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0); + a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG); + + b1 = a(InstructionFactory.createBranchInstruction(IFGT,null)); + a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0); + if(d) { + a(InstructionConstants.DUP2_X2); + a(InstructionConstants.POP2); + } else { + a(InstructionConstants.POP); + } + a(InstructionConstants.DSUB); + + b1.setTarget(setDouble(d)); + + break; + case 6: // MOV.X + preSetReg(F+fd); + pushReg(F+fs); + setReg(); + + preSetReg(F+fd+1); + pushReg(F+fs+1); + setReg(); + + break; + case 7: // NEG.X + preSetDouble(F+fd,d); + pushDouble(F+fs,d); + a(d ? InstructionConstants.DNEG : InstructionConstants.FNEG); + setDouble(d); + break; + case 32: // CVT.S.X + preSetFloat(F+fd); + pushDouble(F+fd,d); + if(d) a(InstructionConstants.D2F); + setFloat(); + break; + case 33: // CVT.D.X + preSetDouble(F+fd); + pushDouble(F+fd,d); + if(!d) a(InstructionConstants.F2D); + setDouble(); + break; + case 36: { // CVT.W.D + int[] matches = new int[4]; + for(int i=0;i<4;i++) matches[i] = i; + + TABLESWITCH ts = new TABLESWITCH(matches,new InstructionHandle[4], null); + + preSetReg(F+fd); + pushDouble(F+fs,d); + pushReg(FCSR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(ts); + + // Round towards plus infinity + ts.setTarget(2,a(InstructionConstants.NOP)); + if(!d) a(InstructionConstants.F2D); // Ugh.. java.lang.Math doesn't have a float ceil/floor + a(fac.createInvoke("java.lang.Math","ceil",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC)); + if(!d) a(InstructionConstants.D2F); + b1 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + + // Round to nearest + ts.setTarget(0,d ? pushConst(0.5d) : pushConst(0.5f)); + a(d ? InstructionConstants.DADD : InstructionConstants.FADD); + // fall through + + // Round towards minus infinity + ts.setTarget(3,a(InstructionConstants.NOP)); + if(!d) a(InstructionConstants.F2D); + a(fac.createInvoke("java.lang.Math","floor",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC)); + if(!d) a(InstructionConstants.D2F); + + InstructionHandle h = a(d ? InstructionConstants.D2I : InstructionConstants.F2I); + setReg(); + + ts.setTarget(1,h); + ts.setTarget(h); + b1.setTarget(h); + + break; + } + case 50: // C.EQ.D + case 60: // C.LT.D + case 62: // C.LE.D + preSetReg(FCSR); + pushReg(FCSR); + pushConst(~0x800000); + a(InstructionConstants.IAND); + pushDouble(F+fs,d); + pushDouble(F+ft,d); + a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG); + switch(subcode) { + case 50: b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null)); break; + case 60: b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); break; + case 62: b1 = a(InstructionFactory.createBranchInstruction(IFLE,null)); break; + default: b1 = null; + } + + pushConst(0x000000); + b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + b1.setTarget(pushConst(0x800000)); + b2.setTarget(a(InstructionConstants.IOR)); + setReg(); + break; + default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); + } + break; + } + case 20: { // Integer + switch(subcode) { + case 32: // CVT.S.W + preSetFloat(F+fd); + pushReg(F+fs); + a(InstructionConstants.I2F); + setFloat(); + break; + case 33: // CVT.D.W + preSetDouble(F+fd); + pushReg(F+fs); + a(InstructionConstants.I2D); + setDouble(); + break; + default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); + } + break; + } + default: + throw new Exn("Invalid Instruction 17/" + rs); + } + break; + } + case 18: case 19: + throw new Exn("coprocessor 2 and 3 instructions not available"); + case 32: { // LB + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.I2B); + setReg(); + break; + } + case 33: { // LH + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.I2S); + setReg(); + break; + } + case 34: { // LWL; + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); // addr + + pushRegWZ(R+rt); + pushConst(0x00ffffff); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.IAND); + + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IOR); + + setReg(); + + break; + + } + case 35: // LW + preSetReg(R+rt); + memRead(R+rs,signedImmediate); + setReg(); + break; + case 36: { // LBU + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + pushConst(0xff); + a(InstructionConstants.IAND); + setReg(); + break; + } + case 37: { // LHU + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + + // chars are unsigend so this works + a(InstructionConstants.I2C); + setReg(); + break; + } + case 38: { // LWR + preSetReg(R+rt); + addiu(R+rs,signedImmediate); + setTmp(); // addr + + pushRegWZ(R+rt); + pushConst(0xffffff00); + pushTmp(); + + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IAND); + + preMemRead(); + pushTmp(); + memRead(true); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.IOR); + + + setReg(); + break; + } + case 40: { // SB + addiu(R+rs,signedImmediate); + setTmp(); // addr + + // FEATURE: DO the preMemRead(true) thing for the rest of the S* instructions + preMemRead(true); + pushTmp(); + memRead(true); + + pushConst(0xff000000); + pushTmp(); + + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.IAND); + + if(rt != 0) { + pushReg(R+rt); + pushConst(0xff); + a(InstructionConstants.IAND); + } else { + pushConst(0); + } + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IOR); + + memWrite(); + + break; + } + case 41: { // SH + preMemWrite1(); + + addiu(R+rs,signedImmediate); + + a(InstructionConstants.DUP); + setTmp(); // addr + + preMemWrite2(true); + + preMemRead(); + pushTmp(); + memRead(true); + + pushConst(0xffff); + pushTmp(); + + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IAND); + + if(rt != 0) { + pushReg(R+rt); + pushConst(0xffff); + a(InstructionConstants.IAND); + } else { + pushConst(0); + } + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IOR); + + memWrite(); + + break; + } + case 42: { // SWL + preMemWrite1(); + + addiu(R+rs,signedImmediate); + a(InstructionConstants.DUP); + setTmp(); // addr + + preMemWrite2(true); + + preMemRead(); + pushTmp(); + memRead(true); + + pushConst(0xffffff00); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IAND); + + pushRegWZ(R+rt); + pushTmp(); + + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.IOR); + + memWrite(); + break; + + } + case 43: // SW + preMemWrite1(); + preMemWrite2(R+rs,signedImmediate); + pushRegZ(R+rt); + memWrite(); + break; + case 46: { // SWR + preMemWrite1(); + + addiu(R+rs,signedImmediate); + a(InstructionConstants.DUP); + setTmp(); // addr + + preMemWrite2(true); + + preMemRead(); + pushTmp(); + memRead(true); + + pushConst(0x00ffffff); + pushTmp(); + + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.IUSHR); + a(InstructionConstants.IAND); + + pushRegWZ(R+rt); + pushTmp(); + + a(InstructionConstants.ICONST_M1); + a(InstructionConstants.IXOR); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.IAND); + a(InstructionConstants.ICONST_3); + a(InstructionConstants.ISHL); + a(InstructionConstants.ISHL); + a(InstructionConstants.IOR); + + memWrite(); + break; + } + // FEATURE: This need to be atomic if we ever support threads (see SWC0/SC) + case 48: // LWC0/LL + preSetReg(R+rt); + memRead(R+rs,signedImmediate); + setReg(); + break; + + case 49: // LWC1 + preSetReg(F+rt); + memRead(R+rs,signedImmediate); + setReg(); + break; + + /* FEATURE: This needs to fail (set rt to 0) if the memory location was modified + * between the LL and SC if we every support threads. + */ + case 56: // SWC0/SC + preSetReg(R+rt); + preMemWrite1(); + preMemWrite2(R+rs,signedImmediate); + pushReg(R+rt); + memWrite(); + pushConst(1); + setReg(); + break; + + case 57: // SWC1 + preMemWrite1(); + preMemWrite2(R+rs,signedImmediate); + pushReg(F+rt); + memWrite(); + break; + default: + throw new Exn("Invalid Instruction: " + op + " at " + toHex(pc)); + } + return false; + } + + // Helper functions for emitText + + private static final int R = 0; + private static final int F = 32; + private static final int HI = 64; + private static final int LO = 65; + private static final int FCSR = 66; + private static final int REG_COUNT=67; + + private int[] regLocalMapping = new int[REG_COUNT]; + private int[] regLocalReadCount = new int[REG_COUNT]; + private int[] regLocalWriteCount = new int[REG_COUNT]; + private int nextAvailLocal; + + private int getLocalForReg(int reg) { + if(regLocalMapping[reg] != 0) return regLocalMapping[reg]; + if(nextAvailLocal == 0) nextAvailLocal = onePage ? 3 : 4; + regLocalMapping[reg] = nextAvailLocal++; + return regLocalMapping[reg]; + } + + private void fixupRegs() { + InstructionHandle prev = realStart; + for(int i=0;i 0) { + a(InstructionConstants.ALOAD_0); + a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i])); + a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD)); + } + + regLocalMapping[i] = regLocalReadCount[i] = regLocalWriteCount[i] = 0; + } + nextAvailLocal = 0; + } + + private void restoreChangedRegs() { + for(int i=0;i 0) { + a(InstructionConstants.ALOAD_0); + a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i])); + a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD)); + } + } + } + + private String regField(int reg) { + String field; + switch(reg) { + case HI: field = "hi"; break; + case LO: field = "lo"; break; + case FCSR: field = "fcsr"; break; + default: + if(reg > R && reg < R+32) field="r"+(reg-R); + else if(reg >= F && reg < F+32) field="f"+(reg-F); + else throw new IllegalArgumentException(""+reg); + } + return field; + } + + private boolean doLocal(int reg) { return reg == R+2 || reg == R+3 || reg == R+4 || reg == R+29; } + + private InstructionHandle pushRegWZ(int reg) { + if(reg == R+0) { + warn.println("Warning: Pushing r0!"); + new Exception().printStackTrace(warn); + } + return pushRegZ(reg); + } + + private InstructionHandle pushRegZ(int reg) { + if(reg == R+0) return pushConst(0); + else return pushReg(reg); + } + + + private InstructionHandle pushReg(int reg) { + InstructionHandle h; + if(doLocal(reg)) { + regLocalReadCount[reg]++; + h = a(InstructionFactory.createLoad(Type.INT,getLocalForReg(reg))); + } else { + h = a(InstructionConstants.ALOAD_0); + a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, GETFIELD)); + } + return h; + } + + private int preSetRegStackPos; + private int[] preSetRegStack = new int[8]; + + // This can push ONE or ZERO words to the stack. If it pushed one it returns true + private boolean preSetReg(int reg) { + regField(reg); // just to check for validity + preSetRegStack[preSetRegStackPos] = reg; + preSetRegStackPos++; + if(doLocal(reg)) { + return false; + } else { + a(InstructionConstants.ALOAD_0); + return true; + } + } + + private InstructionHandle setReg() { + if(preSetRegStackPos==0) throw new RuntimeException("didn't do preSetReg"); + preSetRegStackPos--; + int reg = preSetRegStack[preSetRegStackPos]; + InstructionHandle h; + if(doLocal(reg)) { + h = a(InstructionFactory.createStore(Type.INT,getLocalForReg(reg))); + regLocalWriteCount[reg]++; + } else { + h = a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, PUTFIELD)); + } + return h; + } + + private InstructionHandle preSetPC() { return a(InstructionConstants.ALOAD_0); } + private InstructionHandle setPC() { return a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD)); } + + //unused - private InstructionHandle pushFloat(int reg) throws CompilationException { return pushDouble(reg,false); } + //unused - private InstructionHandle pushDouble(int reg) throws CompilationException { return pushDouble(reg,true); } + private InstructionHandle pushDouble(int reg, boolean d) throws Exn { + if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg); + InstructionHandle h; + if(d) { + if(reg == F+31) throw new Exn("Tried to use a double in f31"); + h = pushReg(reg+1); + a(InstructionConstants.I2L); + pushConst(32); + a(InstructionConstants.LSHL); + pushReg(reg); + a(InstructionConstants.I2L); + pushConst(0xffffffffL); + a(InstructionConstants.LAND); + a(InstructionConstants.LOR); + //p("invokestatic java/lang/Double/longBitsToDouble(J)D"); + a(fac.createInvoke("java.lang.Double","longBitsToDouble",Type.DOUBLE,new Type[]{Type.LONG},INVOKESTATIC)); + } else { + h = pushReg(reg); + a(fac.createInvoke("java.lang.Float","intBitsToFloat",Type.FLOAT,new Type[]{Type.INT},INVOKESTATIC)); + } + return h; + } + + private void preSetFloat(int reg) { preSetDouble(reg,false); } + private void preSetDouble(int reg) { preSetDouble(reg,true); } + private void preSetDouble(int reg, boolean d) { preSetReg(reg); } + + private InstructionHandle setFloat() throws Exn { return setDouble(false); } + private InstructionHandle setDouble() throws Exn { return setDouble(true); } + private InstructionHandle setDouble(boolean d) throws Exn { + int reg = preSetRegStack[preSetRegStackPos-1]; + if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg); + //p("invokestatic java/lang/Double/doubleToLongBits(D)J"); + InstructionHandle h; + if(d) { + if(reg == F+31) throw new Exn("Tried to use a double in f31"); + h = a(fac.createInvoke("java.lang.Double","doubleToLongBits",Type.LONG,new Type[]{Type.DOUBLE},INVOKESTATIC)); + a(InstructionConstants.DUP2); + pushConst(32); + a(InstructionConstants.LUSHR); + a(InstructionConstants.L2I); + if(preSetReg(reg+1)) + a(InstructionConstants.SWAP); + setReg(); + a(InstructionConstants.L2I); + setReg(); // preSetReg was already done for this by preSetDouble + } else { + h = a(fac.createInvoke("java.lang.Float","floatToRawIntBits",Type.INT,new Type[]{Type.FLOAT},INVOKESTATIC)); + setReg(); + } + return h; + } + + private InstructionHandle pushConst(int n) { + if(n >= 0 && n <= 5) { + switch(n) { + case 0: return a(InstructionConstants.ICONST_0); + case 1: return a(InstructionConstants.ICONST_1); + case 2: return a(InstructionConstants.ICONST_2); + case 3: return a(InstructionConstants.ICONST_3); + case 4: return a(InstructionConstants.ICONST_4); + case 5: return a(InstructionConstants.ICONST_5); + default: return null; + } + } else if(n == -1) { + return a(InstructionConstants.ICONST_M1); + } else if(n >= -128 && n <= 127) { + return a(new BIPUSH((byte) n)); + } else if(n >= -32768 && n <= 32767) { + return a(new SIPUSH((short) n)); + } else { + return a(new PUSH(cp,n)); + } + } + + private InstructionHandle pushConst(long l) { return a(new PUSH(cp,l)); } + private InstructionHandle pushConst(float f) { return a(new PUSH(cp,f)); } + private InstructionHandle pushConst(double d) { return a(new PUSH(cp,d)); } + + private void pushTmp() { a(InstructionConstants.ILOAD_1); } + private void setTmp() { a(InstructionConstants.ISTORE_1); } + + private void addiu(int reg, int offset) { + if(reg != R+0 && offset != 0) { + pushReg(reg); + pushConst(offset); + a(InstructionConstants.IADD); + } else if(reg != R+0) { + pushReg(reg); + } else { + pushConst(offset); + } + } + private int memWriteStage; + private void preMemWrite1() { + if(memWriteStage!=0) throw new Error("pending preMemWrite1/2"); + memWriteStage=1; + if(onePage) + a(InstructionConstants.ALOAD_2); + else if(fastMem) + a(InstructionFactory.createLoad(Type.OBJECT,3)); + else + a(InstructionConstants.ALOAD_0); + } + + private void preMemWrite2(int reg, int offset) { + addiu(reg,offset); + preMemWrite2(); + } + + private void preMemWrite2() { preMemWrite2(false); } + private void preMemWrite2(boolean addrInTmp) { + if(memWriteStage!=1) throw new Error("pending preMemWrite2 or no preMemWrite1"); + memWriteStage=2; + + if(nullPointerCheck) { + a(InstructionConstants.DUP); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.SWAP); + a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL)); + } + + if(onePage) { + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IUSHR); + } else if(fastMem) { + if(!addrInTmp) + a(InstructionConstants.DUP_X1); + pushConst(pageShift); + a(InstructionConstants.IUSHR); + a(InstructionConstants.AALOAD); + if(addrInTmp) + pushTmp(); + else + a(InstructionConstants.SWAP); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IUSHR); + pushConst((pageSize>>2)-1); + a(InstructionConstants.IAND); + } + } + + // pops an address and value off the stack, sets *addr to value + private void memWrite() { + if(memWriteStage!=2) throw new Error("didn't do preMemWrite1 or preMemWrite2"); + memWriteStage=0; + + if(onePage) { + a(InstructionConstants.IASTORE); + } else if(fastMem) { + a(InstructionConstants.IASTORE); + } else { + a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL)); + } + + } + + // reads the word at r[reg]+offset + private void memRead(int reg, int offset) { + preMemRead(); + addiu(reg,offset); + memRead(); + } + + private boolean didPreMemRead; + private boolean preMemReadDoPreWrite; + + private void preMemRead() { preMemRead(false); } + private void preMemRead(boolean preWrite) { + if(didPreMemRead) throw new Error("pending preMemRead"); + didPreMemRead = true; + preMemReadDoPreWrite = preWrite; + if(onePage) + a(InstructionConstants.ALOAD_2); + else if(fastMem) + a(InstructionFactory.createLoad(Type.OBJECT,preWrite ? 3 : 2)); + else + a(InstructionConstants.ALOAD_0); + } + // memRead pops an address off the stack, reads the value at that addr, and pushed the value + // preMemRead MUST be called BEFORE the addresses is pushed + private void memRead() { memRead(false); } + + private void memRead(boolean addrInTmp) { + if(!didPreMemRead) throw new Error("didn't do preMemRead"); + didPreMemRead = false; + if(preMemReadDoPreWrite) + memWriteStage=2; + + if(nullPointerCheck) { + a(InstructionConstants.DUP); + a(InstructionConstants.ALOAD_0); + a(InstructionConstants.SWAP); + a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL)); + } + + if(onePage) { + // p(target + "= page[(" + addr + ")>>>2];"); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IUSHR); + if(preMemReadDoPreWrite) + a(InstructionConstants.DUP2); + a(InstructionConstants.IALOAD); + } else if(fastMem) { + //p(target + " = readPages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"];"); + + if(!addrInTmp) + a(InstructionConstants.DUP_X1); + pushConst(pageShift); + a(InstructionConstants.IUSHR); + a(InstructionConstants.AALOAD); + if(addrInTmp) + pushTmp(); + else + a(InstructionConstants.SWAP); + a(InstructionConstants.ICONST_2); + a(InstructionConstants.IUSHR); + pushConst((pageSize>>2)-1); + a(InstructionConstants.IAND); + if(preMemReadDoPreWrite) + a(InstructionConstants.DUP2); + a(InstructionConstants.IALOAD); + + } else { + if(preMemReadDoPreWrite) + a(InstructionConstants.DUP2); + a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.INT,new Type[]{Type.INT},INVOKEVIRTUAL)); + } + } + + + // This might come in handy for something else + /*private boolean touchesReg(int insn, int reg) { + if((reg < R+0 || reg >= R+32) && reg != FCSR) throw new IllegalArgumentException(""+reg); + if(reg == R+0) return false; // r0 is never modified + int op = (insn >>> 26) & 0xff; // bits 26-31 + int subcode = insn & 0x3f; // bits 0-5 + int rd = (insn >>> 11) & 0x1f; // bits 11-15 + int rt = (insn >>> 16) & 0x1f; // bits 16-20 + int rs = (insn >>> 21) & 0x1f; // bits 21-25 + + switch(op) { + case 0: + if(subcode >= 0 && subcode <= 7) return reg == R+rd; // Shift ops + if(subcode >= 32 && subcode <= 43) return reg == R+rd; // Other math ops + if(subcode >= 24 && subcode <= 27) return reg == HI || reg == LO; // MULT/DIV + break; + case 13: return false; // BREAK + case 17: + switch(rs) { + case 0: return reg == R+rt; // MFC.1 + case 2: return reg == R+rt; // CFC.1 + case 4: return false; // MTC.1 + case 6: return false; // CTC.1 + case 16: // Single + case 17: // Double + if(subcode == 50 || subcode == 60 || subcode == 62) return reg == FCSR; + return false; // everything else just touches f0-f31 + case 20: return false; // Integer - just touches f0-f31 + } + break; + default: + if(op >= 8 && op <= 15) return reg == R+rt; // XXXI instructions + if(op >= 40 && op <= 46) return false; // Memory WRITE ops + if(op == 49) return reg == F+rt; // LWC1 + if(op == 57) return false; // SWC1 + break; + } + warn.println("Unknown instruction in touchesReg()- assuming it modifies all regs " + op + " " + subcode); + new Exception().fillInStackTrace().printStackTrace(warn); + return true; + }*/ +} diff --git a/src/org/xwt/mips/ClassLoader.java b/src/org/xwt/mips/ClassLoader.java new file mode 100644 index 0000000..510d309 --- /dev/null +++ b/src/org/xwt/mips/ClassLoader.java @@ -0,0 +1,44 @@ +package org.xwt.mips; + +import java.io.*; + +// FEATURE: This is just a quick hack, it is really ugly and broken + +public class ClassLoader extends java.lang.ClassLoader { + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class c; + if(name.startsWith("mips.")) { + String path = name.substring(5).replace('.','/') + ".mips"; + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + new ClassFileCompiler(path,name,bos).go(); + bos.close(); + byte[] buf = bos.toByteArray(); + c = defineClass(name,buf,0,buf.length); + } catch(IOException e) { + throw new ClassNotFoundException(name); + } catch(Compiler.Exn e) { + throw new ClassNotFoundException(e.getMessage()); + } + } else { + c = findSystemClass(name); + } + + if(c == null) throw new ClassNotFoundException(name); + if(resolve) resolveClass(c); + return c; + } + + public Class classFromBinary(String path) throws ClassNotFoundException { + if(!path.endsWith(".mips")) throw new IllegalArgumentException("isn't a .mips"); + return loadClass("mips." + path.substring(0,path.length()-5).replace('/','.')); + } + + public Runtime runtimeFromBinary(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + return (Runtime) classFromBinary(path).newInstance(); + } + + public static void main(String[] args) throws Exception { + System.exit(new ClassLoader().runtimeFromBinary(args[0]).run(args)); + } +} diff --git a/src/org/xwt/mips/Compiler.java b/src/org/xwt/mips/Compiler.java new file mode 100644 index 0000000..de457e7 --- /dev/null +++ b/src/org/xwt/mips/Compiler.java @@ -0,0 +1,540 @@ +// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] + +package org.xwt.mips; + +import java.util.*; +import java.io.*; + +import org.xwt.mips.util.SeekableData; +import org.xwt.mips.util.SeekableFile; + +public abstract class Compiler implements Registers { + /** The ELF binary being read */ + protected ELF elf; + + /** The name of the class beging generated */ + protected final String fullClassName; + + /** The name of the binary this class is begin generated from */ + protected String source = "unknown.mips.binary"; + public void setSource(String source) { this.source = source; } + + /** Thrown when the compilation fails for some reason */ + protected static class Exn extends Exception { public Exn(String s) { super(s); } } + + // Set this to true to enable fast memory access + // When this is enabled a Java RuntimeException will be thrown when a page fault occures. When it is disabled + // a FaultException will be throw which is easier to catch and deal with, however. as the name implies, this is slower + protected boolean fastMem = true; + + // This MUST be a power of two. If it is not horrible things will happen + // NOTE: This value can be much higher without breaking the classfile + // specs (around 1024) but Hotstop seems to do much better with smaller + // methods. + protected int maxInsnPerMethod = 128; + + // non-configurable + protected int maxBytesPerMethod; + protected int methodMask; + protected int methodShift; + protected void maxInsnPerMethodInit() throws Exn { + if((maxInsnPerMethod&(maxInsnPerMethod-1)) != 0) throw new Exn("maxBytesPerMethod is not a power of two"); + maxBytesPerMethod = maxInsnPerMethod*4; + methodMask = ~(maxBytesPerMethod-1); + while(maxBytesPerMethod>>>methodShift != 1) methodShift++; + } + + // True to try to determine which case statement are needed and only include them + protected boolean pruneCases = true; + + protected boolean assumeTailCalls = true; + + protected boolean optimizedMemcpy = true; + + // True to insert some code in the output to help diagnore compiler problems + protected boolean debugCompiler = false; + + // True to print various statistics about the compilation + protected boolean printStats = false; + + // True to generate runtime statistics that slow execution down significantly + protected boolean runtimeStats = false; + + protected boolean supportCall = true; + + protected boolean nullPointerCheck = false; + + protected String runtimeClass = "org.xwt.mips.Runtime"; + + protected String hashClass = "java.util.Hashtable"; + + protected boolean unixRuntime; + + protected boolean lessConstants = false; + + protected int pageSize = 4096; + protected int totalPages = 65536; + protected int pageShift; + protected boolean onePage; + + protected void pageSizeInit() throws Exn { + try { + Runtime.checkPageSize(pageSize,totalPages); + } catch(IllegalArgumentException e) { + throw new Exn(e.getMessage()); + } + while(pageSize>>>pageShift != 1) pageShift++; + } + + /** The address of the memcpy function in the binary (used for optimizedMemcpy) */ + protected int memcpy; + + /** The address of the memset function in the binary (used for optimizedMemcpy) */ + protected int memset; + + /** A set of all addresses that can be jumped too (only available if pruneCases == true) */ + protected Set jumpableAddresses; + + /** Some important symbols */ + ELF.Symbol userInfo, gp; + + private static void usage() { + System.err.println("Usage: java Compiler [-outfile output.java] [-o options] [-dumpoptions] "); + System.err.println("-o takes mount(8) like options and can be specified multiple times"); + System.err.println("Available options:"); + for(int i=0;i 0) { + if(args[arg].equals("-outfile")) { + arg++; + if(arg==args.length) usage(); + outfile = args[arg]; + } else if(args[arg].equals("-outformat")) { + arg++; + if(arg==args.length) usage(); + outformat = args[arg]; + } else if(args[arg].equals("-o")) { + arg++; + if(arg==args.length) usage(); + if(o==null || o.length() == 0) + o = args[arg]; + else if(args[arg].length() != 0) + o += "," + args[arg]; + } else if(args[arg].equals("-dumpoptions")) { + dumpOptions = true; + } else if(className == null) { + className = args[arg]; + } else if(mipsBinaryFileName == null) { + mipsBinaryFileName = args[arg]; + } else { + usage(); + } + arg++; + } + if(className == null || mipsBinaryFileName == null) usage(); + + SeekableData mipsBinary = new SeekableFile(mipsBinaryFileName); + + Writer w = null; + OutputStream os = null; + Compiler comp = null; + if(outformat == null || outformat.equals("class")) { + if(outfile == null) { + System.err.println("Refusing to write a classfile to stdout - use -outfile foo.class"); + System.exit(1); + } + os = new FileOutputStream(outfile); + comp = new ClassFileCompiler(mipsBinary,className,os); + } else if(outformat.equals("javasource") || outformat .equals("java")) { + w = outfile == null ? new OutputStreamWriter(System.out): new FileWriter(outfile); + comp = new JavaSourceCompiler(mipsBinary,className,w); + } else { + System.err.println("Unknown output format: " + outformat); + System.exit(1); + } + + comp.parseOptions(o); + comp.setSource(mipsBinaryFileName); + + if(dumpOptions) { + System.err.println("== Options =="); + for(int i=0;i>> 26) & 0xff; + int rs = (insn >>> 21) & 0x1f; + int rt = (insn >>> 16) & 0x1f; + int signedImmediate = (insn << 16) >> 16; + int unsignedImmediate = insn & 0xffff; + int branchTarget = signedImmediate; + int jumpTarget = (insn & 0x03ffffff); + int subcode = insn & 0x3f; + + switch(op) { + case 0: + switch(subcode) { + case 9: // JALR + if(jumps.add(new Integer(pc+8))) n++; // return address + break; + case 12: // SYSCALL + if(jumps.add(new Integer(pc+4))) n++; + break; + } + break; + case 1: + switch(rt) { + case 16: // BLTZAL + case 17: // BGTZAL + if(jumps.add(new Integer(pc+8))) n++; // return address + // fall through + case 0: // BLTZ + case 1: // BGEZ + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + } + break; + case 3: // JAL + if(jumps.add(new Integer(pc+8))) n++; // return address + // fall through + case 2: // J + if(jumps.add(new Integer((pc&0xf0000000)|(jumpTarget << 2)))) n++; + break; + case 4: // BEQ + case 5: // BNE + case 6: // BLEZ + case 7: // BGTZ + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + case 9: { // ADDIU + if(pc - lui_pc[rs] <= 4*32) { + int t = (lui_val[rs]<<16)+signedImmediate; + if((t&3)==0 && t >= base && t < base+size) { + if(jumps.add(new Integer(t))) { + //System.err.println("Possible jump to " + toHex(t) + " (" + inter.sourceLine(t) + ") from " + toHex(pc) + " (" + inter.sourceLine(pc) + ")"); + n++; + } + } + // we just blew it away + if(rt == rs) lui_pc[rs] = 0; + } + break; + } + case 15: { // LUI + lui_val[rt] = unsignedImmediate; + lui_pc[rt] = pc; + break; + } + + case 17: // FPU Instructions + switch(rs) { + case 8: // BC1F, BC1T + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + } + break; + } + } + dis.close(); + if(printStats) System.err.println("Found " + n + " additional possible branch targets in Text segment"); + } + + private void findBranchesInData(DataInputStream dis, int size, Set jumps, int textStart, int textEnd) throws IOException { + int count = size/4; + int n=0; + for(int i=0;i= textStart && word < textEnd) { + if(jumps.add(new Integer(word))) { + //System.err.println("Added " + toHex(word) + " as possible branch target (fron data segment)"); + n++; + } + } + } + dis.close(); + if(n>0 && printStats) System.err.println("Found " + n + " additional possible branch targets in Data segment"); + } + + // Helper functions for pretty output + protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } + protected final static String toHex8(int n) { + String s = Long.toString(n & 0xffffffffL, 16); + StringBuffer sb = new StringBuffer("0x"); + for(int i=8-s.length();i>0;i--) sb.append('0'); + sb.append(s); + return sb.toString(); + } + + protected final static String toOctal3(int n) { + char[] buf = new char[3]; + for(int i=2;i>=0;i--) { + buf[i] = (char) ('0' + (n & 7)); + n >>= 3; + } + return new String(buf); + } + + // Option parsing + private class Option { + private java.lang.reflect.Field field; + public Option(String name) throws NoSuchFieldException { field = name==null ? null : Compiler.class.getDeclaredField(name); } + public void set(Object val) { + if(field == null) return; + try { + field.setAccessible(true); + field.set(Compiler.this,val); + } catch(IllegalAccessException e) { + System.err.println(e); + } + } + public Object get() { + if(field == null) return null; + try { + field.setAccessible(true); + return field.get(Compiler.this); + } catch(IllegalAccessException e) { + System.err.println(e); return null; + } + } + public Class getType() { return field == null ? null : field.getType(); } + } + + private static String[] options = { + "fastMem", "Enable fast memory access - RuntimeExceptions will be thrown on faults", + "nullPointerCheck", "Enables checking at runtime for null pointer accessses (slows things down a bit, only applicable with fastMem)", + "maxInsnPerMethod", "Maximum number of MIPS instructions per java method (128 is optimal with Hotspot)", + "pruneCases", "Remove unnecessary case 0xAABCCDD blocks from methods - may break some weird code", + "assumeTailCalls", "Assume the JIT optimizes tail calls", + "optimizedMemcpy", "Use an optimized java version of memcpy where possible", + "debugCompiler", "Output information in the generated code for debugging the compiler - will slow down generated code significantly", + "printStats", "Output some useful statistics about the compilation", + "runtimeStats", "Keep track of some statistics at runtime in the generated code - will slow down generated code significantly", + "supportCall", "Keep a stripped down version of the symbol table in the generated code to support the call() method", + "runtimeClass", "Full classname of the Runtime class (default: Runtime) - use this is you put Runtime in a package", + "hashClass", "Full classname of a Hashtable class (default: java.util.HashMap) - this must support get() and put()", + "unixRuntime", "Use the UnixRuntime (has support for fork, wai, du, pipe, etc)", + "pageSize", "The page size (must be a power of two)", + "totalPages", "Total number of pages (total mem = pageSize*totalPages, must be a power of two)", + "onePage", "One page hack (FIXME: document this better)", + "lessConstants", "Use less constants at the cost of speed (FIXME: document this better)" + }; + + private Option getOption(String name) { + name = name.toLowerCase(); + try { + for(int i=0;i 2 && s.startsWith("0x")) n = Integer.parseInt(s.substring(2),16); + else n = Integer.parseInt(s); + return new Integer(n*mult); + } + + private static String wrapAndIndent(String s, int firstindent, int indent, int width) { + StringTokenizer st = new StringTokenizer(s," "); + StringBuffer sb = new StringBuffer(); + for(int i=0;i width && sofar > 0) { + sb.append('\n'); + for(int i=0;i 0) { + sb.append(' '); + sofar++; + } + sb.append(tok); + sofar += tok.length(); + } + sb.append('\n'); + return sb.toString(); + } + + // This ugliness is to work around a gcj static linking bug (Bug 12908) + // The best solution is to force gnu.java.locale.Calendar to be linked in but this'll do + protected static String dateTime() { + try { + return new Date().toString(); + } catch(RuntimeException e) { + return ""; + } + } +} + diff --git a/src/org/xwt/mips/ELF.java b/src/org/xwt/mips/ELF.java new file mode 100644 index 0000000..18698f2 --- /dev/null +++ b/src/org/xwt/mips/ELF.java @@ -0,0 +1,381 @@ +package org.xwt.mips; + +import org.xwt.mips.util.*; +import java.io.*; + +public class ELF { + private SeekableData data; + + public ELFIdent ident; + public ELFHeader header; + public PHeader[] pheaders; + public SHeader[] sheaders; + + private byte[] stringTable; + + private boolean sectionReaderActive; + + + private void readFully(byte[] buf) throws IOException { + int len = buf.length; + int pos = 0; + while(len > 0) { + int n = data.read(buf,pos,len); + if(n == -1) throw new IOException("EOF"); + pos += n; + len -= n; + } + } + + private int readIntBE() throws IOException { + byte[] buf = new byte[4]; + readFully(buf); + return ((buf[0]&0xff)<<24)|((buf[1]&0xff)<<16)|((buf[2]&0xff)<<8)|((buf[3]&0xff)<<0); + } + private int readInt() throws IOException { + int x = readIntBE(); + if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) + x = ((x<<24)&0xff000000) | ((x<<8)&0xff0000) | ((x>>>8)&0xff00) | ((x>>24)&0xff); + return x; + } + + private short readShortBE() throws IOException { + byte[] buf = new byte[2]; + readFully(buf); + return (short)(((buf[0]&0xff)<<8)|((buf[1]&0xff)<<0)); + } + private short readShort() throws IOException { + short x = readShortBE(); + if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) + x = (short)((((x<<8)&0xff00) | ((x>>8)&0xff))&0xffff); + return x; + } + + private byte readByte() throws IOException { + byte[] buf = new byte[1]; + readFully(buf); + return buf[0]; + } + + public class ELFIdent { + private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F' + + public static final int ELFCLASSNONE = 0; + public static final int ELFCLASS32 = 1; + public static final int ELFCLASS64 = 2; + public byte klass; + + + public static final int ELFDATANONE = 0; + public static final int ELFDATA2LSB = 1; + public static final int ELFDATA2MSB = 2; + public byte data; + public byte osabi; + public byte abiversion; + + ELFIdent() throws IOException { + if(readIntBE() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " ); + + klass = readByte(); + if(klass != ELFCLASS32) throw new ELFException("org.xwt.mips.ELF does not suport 64-bit binaries"); + + data = readByte(); + if(data != ELFDATA2LSB && data != ELFDATA2MSB) throw new ELFException("Unknown byte order"); + + readByte(); // version + osabi = readByte(); + abiversion = readByte(); + for(int i=0;i<7;i++) readByte(); // padding + } + } + + public class ELFHeader { + public static final short ET_EXEC = 2; + public short type; + + public static final short EM_MIPS = 8; + public short machine; + + public int version; + public int entry; + public int phoff; + public int shoff; + public int flags; + public short ehsize; + public short phentsize; + public short phnum; + public short shentsize; + public short shnum; + public short shstrndx; + + ELFHeader() throws IOException { + type = readShort(); + machine = readShort(); + version = readInt(); + if(version != 1) throw new ELFException("version != 1"); + entry = readInt(); + phoff = readInt(); + shoff = readInt(); + flags = readInt(); + ehsize = readShort(); + phentsize = readShort(); + phnum = readShort(); + shentsize = readShort(); + shnum = readShort(); + shstrndx = readShort(); + } + } + + public class PHeader { + public int type; + public int offset; + public int vaddr; + public int paddr; + public int filesz; + public int memsz; + public int flags; + public int align; + + public static final int PF_X = 0x1; + public static final int PF_W = 0x2; + public static final int PF_R = 0x4; + + public static final int PT_LOAD = 1; + + PHeader() throws IOException { + type = readInt(); + offset = readInt(); + vaddr = readInt(); + paddr = readInt(); + filesz = readInt(); + memsz = readInt(); + flags = readInt(); + align = readInt(); + if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz (" + toHex(filesz) + " > " + toHex(memsz) + ")"); + } + + public boolean writable() { return (flags & PF_W) != 0; } + + public InputStream getInputStream() throws IOException { + return new BufferedInputStream(new SectionInputStream( + offset,offset+filesz)); + } + } + + public class SHeader { + int nameidx; + public String name; + public int type; + public int flags; + public int addr; + public int offset; + public int size; + public int link; + public int info; + public int addralign; + public int entsize; + + public static final int SHT_SYMTAB = 2; + public static final int SHT_STRTAB = 3; + public static final int SHT_NOBITS = 8; + + SHeader() throws IOException { + nameidx = readInt(); + type = readInt(); + flags = readInt(); + addr = readInt(); + offset = readInt(); + size = readInt(); + link = readInt(); + info = readInt(); + addralign = readInt(); + entsize = readInt(); + } + + public InputStream getInputStream() throws IOException { + return new BufferedInputStream(new SectionInputStream( + offset, type == SHT_NOBITS ? 0 : offset+size)); + } + + public boolean isText() { return name.equals(".text"); } + public boolean isData() { return name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"); } + public boolean isBSS() { return name.equals(".bss") || name.equals(".sbss"); } + } + + public ELF(String file) throws IOException, ELFException { this(new SeekableFile(file,false)); } + public ELF(SeekableData data) throws IOException, ELFException { + this.data = data; + ident = new ELFIdent(); + header = new ELFHeader(); + pheaders = new PHeader[header.phnum]; + for(int i=0;i= header.shnum) throw new ELFException("Bad shstrndx"); + data.seek(sheaders[header.shstrndx].offset); + stringTable = new byte[sheaders[header.shstrndx].size]; + readFully(stringTable); + + for(int i=0;i= strtab.length) return ""; + while(off >= 0 && off < strtab.length && strtab[off] != 0) sb.append((char)strtab[off++]); + return sb.toString(); + } + + public SHeader sectionWithName(String name) { + for(int i=0;i 0) pos += n; return n; + } + public void close() { sectionReaderActive = false; } + } + + private Symtab _symtab; + public Symtab getSymtab() throws IOException { + if(_symtab != null) return _symtab; + + if(sectionReaderActive) throw new ELFException("Can't read the symtab while a section reader is active"); + + SHeader sh = sectionWithName(".symtab"); + if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null; + + SHeader sth = sectionWithName(".strtab"); + if(sth == null || sth.type != SHeader.SHT_STRTAB) return null; + + byte[] strtab = new byte[sth.size]; + DataInputStream dis = new DataInputStream(sth.getInputStream()); + dis.readFully(strtab); + dis.close(); + + return _symtab = new Symtab(sh.offset, sh.size,strtab); + } + + public class Symtab { + public Symbol[] symbols; + + Symtab(int off, int size, byte[] strtab) throws IOException { + data.seek(off); + int count = size/16; + symbols = new Symbol[count]; + for(int i=0;i>4); + other = readByte(); + // FEATURE: This should point to some other entry or something + readShort(); + } + } + + private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } + + public static void main(String[] args) throws IOException { + ELF elf = new ELF(new SeekableInputStream(new FileInputStream(args[0]))); + System.out.println("Type: " + toHex(elf.header.type)); + System.out.println("Machine: " + toHex(elf.header.machine)); + System.out.println("Entry: " + toHex(elf.header.entry)); + for(int i=0;i " + toHex(symtab.symbols[i].addr)); + } else { + System.out.println("Symbol table: None"); + } + } +} diff --git a/src/org/xwt/mips/Interpreter.java b/src/org/xwt/mips/Interpreter.java new file mode 100644 index 0000000..f95df92 --- /dev/null +++ b/src/org/xwt/mips/Interpreter.java @@ -0,0 +1,757 @@ +// Copyright 2003 Brian Alliet +// Based on org.xwt.imp.MIPS by Adam Megacz +// Portions Copyright 2003 Adam Megacz + +package org.xwt.mips; + +import org.xwt.mips.util.*; +import java.io.*; + +public class Interpreter extends UnixRuntime { + // Registers + private int[] registers = new int[32]; + private int hi,lo; + + // Floating Point Registers + private int[] fpregs = new int[32]; + // 24-31 - unused + // 23 - conditional bit + // 18-22 - unused + // 12-17 - cause bits (unimplemented) + // 7-11 - enables bits (unimplemented) + // 2-6 - flags (unimplemented) + // 0-1 - rounding mode (only implemented for fixed point conversions) + private int fcsr; + + private int pc; + + // The filename if the binary we're running + public String image; + private ELF.Symtab symtab; + + // Register Operations + private final void setFC(boolean b) { fcsr = (fcsr&~0x800000) | (b ? 0x800000 : 0x000000); } + private final int roundingMode() { return fcsr & 3; /* bits 0-1 */ } + private final double getDouble(int r) { + return Double.longBitsToDouble(((fpregs[r+1]&0xffffffffL) << 32) | (fpregs[r]&0xffffffffL)); + } + private final void setDouble(int r, double d) { + long l = Double.doubleToLongBits(d); + fpregs[r+1] = (int)(l >>> 32); fpregs[r] = (int)l; + } + private final float getFloat(int r) { return Float.intBitsToFloat(fpregs[r]); } + private final void setFloat(int r, float f) { fpregs[r] = Float.floatToRawIntBits(f); } + + protected void _execute() throws ExecutionException { + try { + runSome(); + } catch(ExecutionException e) { + e.setLocation(toHex(pc) + ": " + sourceLine(pc)); + throw e; + } + } + + // Main interpretor + // the return value is meaningless, its just to catch people typing "return" by accident + private final int runSome() throws FaultException,ExecutionException { + int[] r = registers; + int[] f = fpregs; + int pc = this.pc; + int nextPC = pc + 4; + try { + OUTER: for(;;) { + int insn; + try { + insn = readPages[pc>>>PAGE_SHIFT][(pc>>>2)&PAGE_WORDS-1]; + } catch (RuntimeException e) { + insn = memRead(pc); + } + + int op = (insn >>> 26) & 0xff; // bits 26-31 + int rs = (insn >>> 21) & 0x1f; // bits 21-25 + int rt = (insn >>> 16) & 0x1f; // bits 16-20 + int ft = (insn >>> 16) & 0x1f; + int rd = (insn >>> 11) & 0x1f; // bits 11-15 + int fs = (insn >>> 11) & 0x1f; + int shamt = (insn >>> 6) & 0x1f; // bits 6-10 + int fd = (insn >>> 6) & 0x1f; + int subcode = insn & 0x3f; // bits 0-5 + + int jumpTarget = (insn & 0x03ffffff); // bits 0-25 + int unsignedImmediate = insn & 0xffff; + int signedImmediate = (insn << 16) >> 16; + int branchTarget = signedImmediate; + + int tmp, addr; // temporaries + + r[ZERO] = 0; + + switch(op) { + case 0: { + switch(subcode) { + case 0: // SLL + if(insn == 0) break; + r[rd] = r[rt] << shamt; + break; + case 2: // SRL + r[rd] = r[rt] >>> shamt; + break; + case 3: // SRA + r[rd] = r[rt] >> shamt; + break; + case 4: // SLLV + r[rd] = r[rt] << (r[rs]&0x1f); + break; + case 6: // SRLV + r[rd] = r[rt] >>> (r[rs]&0x1f); + break; + case 7: // SRAV + r[rd] = r[rt] >> (r[rs]&0x1f); + break; + case 8: // JR + tmp = r[rs]; pc += 4; nextPC = tmp; + continue OUTER; + case 9: // JALR + tmp = r[rs]; pc += 4; r[rd] = pc+4; nextPC = tmp; + continue OUTER; + case 12: // SYSCALL + this.pc = pc; + r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3]); + if(state != RUNNING) { this.pc = nextPC; break OUTER; } + break; + case 13: // BREAK + throw new ExecutionException("Break"); + case 16: // MFHI + r[rd] = hi; + break; + case 17: // MTHI + hi = r[rs]; + break; + case 18: // MFLO + r[rd] = lo; + break; + case 19: // MTLO + lo = r[rs]; + break; + case 24: { // MULT + long hilo = (long)(r[rs]) * ((long)r[rt]); + hi = (int) (hilo >>> 32); + lo = (int) hilo; + break; + } + case 25: { // MULTU + long hilo = (r[rs] & 0xffffffffL) * (r[rt] & 0xffffffffL); + hi = (int) (hilo >>> 32); + lo = (int) hilo; + break; + } + case 26: // DIV + hi = r[rs]%r[rt]; + lo = r[rs]/r[rt]; + break; + case 27: // DIVU + if(rt != 0) { + hi = (int)((r[rs] & 0xffffffffL) % (r[rt] & 0xffffffffL)); + lo = (int)((r[rs] & 0xffffffffL) / (r[rt] & 0xffffffffL)); + } + break; + case 32: // ADD + throw new ExecutionException("ADD (add with oveflow trap) not suported"); + /*This must trap on overflow + r[rd] = r[rs] + r[rt]; + break;*/ + case 33: // ADDU + r[rd] = r[rs] + r[rt]; + break; + case 34: // SUB + throw new ExecutionException("SUB (sub with oveflow trap) not suported"); + /*This must trap on overflow + r[rd] = r[rs] - r[rt]; + break;*/ + case 35: // SUBU + r[rd] = r[rs] - r[rt]; + break; + case 36: // AND + r[rd] = r[rs] & r[rt]; + break; + case 37: // OR + r[rd] = r[rs] | r[rt]; + break; + case 38: // XOR + r[rd] = r[rs] ^ r[rt]; + break; + case 39: // NOR + r[rd] = ~(r[rs] | r[rt]); + break; + case 42: // SLT + r[rd] = r[rs] < r[rt] ? 1 : 0; + break; + case 43: // SLTU + r[rd] = ((r[rs] & 0xffffffffL) < (r[rt] & 0xffffffffL)) ? 1 : 0; + break; + default: + throw new ExecutionException("Illegal instruction 0/" + subcode); + } + break; + } + case 1: { + switch(rt) { + case 0: // BLTZ + if(r[rs] < 0) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 1: // BGEZ + if(r[rs] >= 0) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 16: // BLTZAL + if(r[rs] < 0) { + pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 17: // BGEZAL + if(r[rs] >= 0) { + pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + default: + throw new ExecutionException("Illegal Instruction"); + } + break; + } + case 2: { // J + tmp = (pc&0xf0000000) | (jumpTarget << 2); + pc+=4; nextPC = tmp; + continue OUTER; + } + case 3: { // JAL + tmp = (pc&0xf0000000) | (jumpTarget << 2); + pc+=4; r[RA] = pc+4; nextPC = tmp; + continue OUTER; + } + case 4: // BEQ + if(r[rs] == r[rt]) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 5: // BNE + if(r[rs] != r[rt]) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 6: //BLEZ + if(r[rs] <= 0) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 7: //BGTZ + if(r[rs] > 0) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 8: // ADDI + r[rt] = r[rs] + signedImmediate; + break; + case 9: // ADDIU + r[rt] = r[rs] + signedImmediate; + break; + case 10: // SLTI + r[rt] = r[rs] < signedImmediate ? 1 : 0; + break; + case 11: // SLTIU + r[rt] = (r[rs]&0xffffffffL) < (unsignedImmediate&0xffffffffL) ? 1 : 0; + break; + case 12: // ANDI + r[rt] = r[rs] & unsignedImmediate; + break; + case 13: // ORI + r[rt] = r[rs] | unsignedImmediate; + break; + case 14: // XORI + r[rt] = r[rs] ^ unsignedImmediate; + break; + case 15: // LUI + r[rt] = unsignedImmediate << 16; + break; + case 16: + throw new ExecutionException("TLB/Exception support not implemented"); + case 17: { // FPU + boolean debug = false; + String line = debug ? sourceLine(pc) : ""; + boolean debugon = debug && (line.indexOf("dtoa.c:51") >= 0 || line.indexOf("dtoa.c:52") >= 0 || line.indexOf("test.c") >= 0); + if(rs > 8 && debugon) + System.out.println(" FP Op: " + op + "/" + rs + "/" + subcode + " " + line); + if(roundingMode() != 0 && rs != 6 /*CTC.1*/ && !((rs==16 || rs==17) && subcode == 36 /* CVT.W.Z */)) + throw new ExecutionException("Non-cvt.w.z operation attempted with roundingMode != round to nearest"); + switch(rs) { + case 0: // MFC.1 + r[rt] = f[rd]; + break; + case 2: // CFC.1 + if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable"); + r[rt] = fcsr; + break; + case 4: // MTC.1 + f[rd] = r[rt]; + break; + case 6: // CTC.1 + if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable"); + fcsr = r[rt]; + break; + case 8: // BC1F, BC1T + if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) { + pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; + continue OUTER; + } + break; + case 16: { // Single + switch(subcode) { + case 0: // ADD.S + setFloat(fd,getFloat(fs)+getFloat(ft)); + break; + case 1: // SUB.S + setFloat(fd,getFloat(fs)-getFloat(ft)); + break; + case 2: // MUL.S + setFloat(fd,getFloat(fs)*getFloat(ft)); + break; + case 3: // DIV.S + setFloat(fd,getFloat(fs)/getFloat(ft)); + break; + case 5: // ABS.S + setFloat(fd,Math.abs(getFloat(fs))); + break; + case 6: // MOV.S + f[fd] = f[fs]; + break; + case 7: // NEG.S + setFloat(fd,-getFloat(fs)); + break; + case 33: // CVT.D.S + setDouble(fd,getFloat(fs)); + break; + case 36: // CVT.W.S + switch(roundingMode()) { + case 0: f[fd] = (int)Math.floor(getFloat(fs)+0.5f); break; // Round to nearest + case 1: f[fd] = (int)getFloat(fs); break; // Round towards zero + case 2: f[fd] = (int)Math.ceil(getFloat(fs)); break; // Round towards plus infinity + case 3: f[fd] = (int)Math.floor(getFloat(fs)); break; // Round towards minus infinity + } + break; + case 50: // C.EQ.S + setFC(getFloat(fs) == getFloat(ft)); + break; + case 60: // C.LT.S + setFC(getFloat(fs) < getFloat(ft)); + break; + default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + } + break; + } + case 17: { // Double + switch(subcode) { + case 0: // ADD.D + setDouble(fd,getDouble(fs)+getDouble(ft)); + break; + case 1: // SUB.D + if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") - f" + ft + " (" + getDouble(ft) + ")"); + setDouble(fd,getDouble(fs)-getDouble(ft)); + break; + case 2: // MUL.D + if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") * f" + ft + " (" + getDouble(ft) + ")"); + setDouble(fd,getDouble(fs)*getDouble(ft)); + if(debugon) System.out.println("f" + fd + " = " + getDouble(fd)); + break; + case 3: // DIV.D + setDouble(fd,getDouble(fs)/getDouble(ft)); + break; + case 5: // ABS.D + setDouble(fd,Math.abs(getDouble(fs))); + break; + case 6: // MOV.D + f[fd] = f[fs]; + f[fd+1] = f[fs+1]; + break; + case 7: // NEG.D + setDouble(fd,-getDouble(fs)); + break; + case 32: // CVT.S.D + setFloat(fd,(float)getDouble(fs)); + break; + case 36: // CVT.W.D + if(debugon) System.out.println("CVT.W.D rm: " + roundingMode() + " f" + fs + ":" + getDouble(fs)); + switch(roundingMode()) { + case 0: f[fd] = (int)Math.floor(getDouble(fs)+0.5); break; // Round to nearest + case 1: f[fd] = (int)getDouble(fs); break; // Round towards zero + case 2: f[fd] = (int)Math.ceil(getDouble(fs)); break; // Round towards plus infinity + case 3: f[fd] = (int)Math.floor(getDouble(fs)); break; // Round towards minus infinity + } + if(debugon) System.out.println("CVT.W.D: f" + fd + ":" + f[fd]); + break; + case 50: // C.EQ.D + setFC(getDouble(fs) == getDouble(ft)); + break; + case 60: // C.LT.D + setFC(getDouble(fs) < getDouble(ft)); + break; + case 62: // C.LE.D + setFC(getDouble(fs) <= getDouble(ft)); + break; + default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + } + break; + } + case 20: { // Integer + switch(subcode) { + case 33: // CVT.D.W + setDouble(fd,f[fs]); + break; + default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + } + break; + } + default: + throw new ExecutionException("Invalid Instruction 17/" + rs); + } + break; + } + case 18: case 19: + throw new ExecutionException("No coprocessor installed"); + case 32: { // LB + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&3) { + case 0: tmp = (tmp>>>24)&0xff; break; + case 1: tmp = (tmp>>>16)&0xff; break; + case 2: tmp = (tmp>>> 8)&0xff; break; + case 3: tmp = (tmp>>> 0)&0xff; break; + } + if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend + r[rt] = tmp; + break; + } + case 33: { // LH + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&2) { + case 0: tmp = (tmp>>>16)&0xffff; break; + case 2: tmp = (tmp>>> 0)&0xffff; break; + } + if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend + r[rt] = tmp; + break; + } + case 34: { // LWL; + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&3) { + case 0: r[rt] = (r[rt]&0x00000000)|(tmp<< 0); break; + case 1: r[rt] = (r[rt]&0x000000ff)|(tmp<< 8); break; + case 2: r[rt] = (r[rt]&0x0000ffff)|(tmp<<16); break; + case 3: r[rt] = (r[rt]&0x00ffffff)|(tmp<<24); break; + } + break; + } + case 35: // LW + addr = r[rs] + signedImmediate; + try { + r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + r[rt] = memRead(addr); + } + break; + case 36: { // LBU + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr); + } + switch(addr&3) { + case 0: r[rt] = (tmp>>>24)&0xff; break; + case 1: r[rt] = (tmp>>>16)&0xff; break; + case 2: r[rt] = (tmp>>> 8)&0xff; break; + case 3: r[rt] = (tmp>>> 0)&0xff; break; + } + break; + } + case 37: { // LHU + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&2) { + case 0: r[rt] = (tmp>>>16)&0xffff; break; + case 2: r[rt] = (tmp>>> 0)&0xffff; break; + } + break; + } + case 38: { // LWR + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&3) { + case 0: r[rt] = (r[rt]&0xffffff00)|(tmp>>>24); break; + case 1: r[rt] = (r[rt]&0xffff0000)|(tmp>>>16); break; + case 2: r[rt] = (r[rt]&0xff000000)|(tmp>>> 8); break; + case 3: r[rt] = (r[rt]&0x00000000)|(tmp>>> 0); break; + } + break; + } + case 40: { // SB + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&3) { + case 0: tmp = (tmp&0x00ffffff) | ((r[rt]&0xff)<<24); break; + case 1: tmp = (tmp&0xff00ffff) | ((r[rt]&0xff)<<16); break; + case 2: tmp = (tmp&0xffff00ff) | ((r[rt]&0xff)<< 8); break; + case 3: tmp = (tmp&0xffffff00) | ((r[rt]&0xff)<< 0); break; + } + try { + writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + } catch(RuntimeException e) { + memWrite(addr&~3,tmp); + } + break; + } + case 41: { // SH + addr = r[rs] + signedImmediate; + try { + tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + } catch(RuntimeException e) { + tmp = memRead(addr&~3); + } + switch(addr&2) { + case 0: tmp = (tmp&0x0000ffff) | ((r[rt]&0xffff)<<16); break; + case 2: tmp = (tmp&0xffff0000) | ((r[rt]&0xffff)<< 0); break; + } + try { + writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + } catch(RuntimeException e) { + memWrite(addr&~3,tmp); + } + break; + } + case 42: { // SWL + addr = r[rs] + signedImmediate; + tmp = memRead(addr&~3); + switch(addr&3) { + case 0: tmp=(tmp&0x00000000)|(r[rt]>>> 0); break; + case 1: tmp=(tmp&0xff000000)|(r[rt]>>> 8); break; + case 2: tmp=(tmp&0xffff0000)|(r[rt]>>>16); break; + case 3: tmp=(tmp&0xffffff00)|(r[rt]>>>24); break; + } + try { + writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + } catch(RuntimeException e) { + memWrite(addr&~3,tmp); + } + break; + } + case 43: // SW + addr = r[rs] + signedImmediate; + try { + writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = r[rt]; + } catch(RuntimeException e) { + memWrite(addr&~3,r[rt]); + } + break; + case 46: { // SWR + addr = r[rs] + signedImmediate; + tmp = memRead(addr&~3); + switch(addr&3) { + case 0: tmp=(tmp&0x00ffffff)|(r[rt]<<24); break; + case 1: tmp=(tmp&0x0000ffff)|(r[rt]<<16); break; + case 2: tmp=(tmp&0x000000ff)|(r[rt]<< 8); break; + case 3: tmp=(tmp&0x00000000)|(r[rt]<< 0); break; + } + memWrite(addr&~3,tmp); + break; + } + // FEATURE: Needs to be atomic w/ threads + case 48: // LWC0/LL + r[rt] = memRead(r[rs] + signedImmediate); + break; + case 49: // LWC1 + f[rt] = memRead(r[rs] + signedImmediate); + break; + // FEATURE: Needs to be atomic w/ threads + case 56: + memWrite(r[rs] + signedImmediate,r[rt]); + r[rt] = 1; + break; + case 57: // SWC1 + memWrite(r[rs] + signedImmediate,f[rt]); + break; + default: + throw new ExecutionException("Invalid Instruction: " + op); + } + pc = nextPC; + nextPC = pc + 4; + } // for(;;) + } catch(ExecutionException e) { + this.pc = pc; + throw e; + } + return 0; + } + + public int lookupSymbol(String name) { + ELF.Symbol sym = symtab.getGlobalSymbol(name); + return sym == null ? -1 : sym.addr; + } + + // Image loading function + private void loadImage(SeekableData data) throws IOException { + if(state != UNINITIALIZED) throw new IllegalStateException("loadImage called on initialized runtime"); + + ELF elf = new ELF(data); + symtab = elf.getSymtab(); + + if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable"); + if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture"); + if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian"); + + entryPoint = elf.header.entry; + + ELF.Symtab symtab = elf.getSymtab(); + if(symtab == null) throw new IOException("No symtab in binary (did you strip it?)"); + ELF.Symbol userInfo = symtab.getGlobalSymbol("user_info"); + ELF.Symbol gpsym = symtab.getGlobalSymbol("_gp"); + + if(gpsym == null) throw new IOException("NO _gp symbol!"); + gp = gpsym.addr; + + if(userInfo != null) { + userInfoBase = userInfo.addr; + userInfoSize = userInfo.size; + } + + ELF.PHeader[] pheaders = elf.pheaders; + int brk = 0; + for(int i=0;i>> PAGE_SHIFT; + if(readPages[page] == null) + readPages[page] = new int[PAGE_WORDS]; + if(ph.writable()) writePages[page] = readPages[page]; + } + if(filesize != 0) { + filesize = filesize & ~3; + DataInputStream dis = new DataInputStream(ph.getInputStream()); + do { + readPages[addr >>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt(); + addr+=4; + filesize-=4; + } while(filesize > 0); + dis.close(); + } + } + brkAddr = (brk+PAGE_SIZE-1)&~(PAGE_SIZE-1); + state = INITIALIZED; + } + + protected void setCPUState(CPUState state) { + for(int i=1;i<32;i++) registers[i] = state.r[i]; + for(int i=0;i<32;i++) fpregs[i] = state.f[i]; + hi=state.hi; lo=state.lo; fcsr=state.fcsr; + pc=state.pc; + } + + protected CPUState getCPUState() { + CPUState state = new CPUState(); + for(int i=1;i<32;i++) state.r[i] = registers[i]; + for(int i=0;i<32;i++) state.f[i] = fpregs[i]; + state.hi=hi; state.lo=lo; state.fcsr=fcsr; + state.pc=pc; + return state; + } + + // This is package private for fork() which does all kinds of ugly things behind the scenes + Interpreter() { super(4096,65536,true); } + public Interpreter(SeekableData data) throws IOException { this(); loadImage(data); } + public Interpreter(String filename) throws IOException { + this(new SeekableFile(filename,false)); + image = filename; + } + public Interpreter(InputStream is) throws IOException { this(new SeekableInputStream(is)); } + + // Debug functions + // NOTE: This probably requires a jdk > 1.1, however, it is only used for debugging + private java.util.HashMap sourceLineCache; + public String sourceLine(int pc) { + final String addr2line = "mips-unknown-elf-addr2line"; + String line = (String) (sourceLineCache == null ? null : sourceLineCache.get(new Integer(pc))); + if(line != null) return line; + if(image==null) return null; + try { + Process p = java.lang.Runtime.getRuntime().exec(new String[]{addr2line,"-e",image,toHex(pc)}); + line = new BufferedReader(new InputStreamReader(p.getInputStream())).readLine(); + if(line == null) return null; + while(line.startsWith("../")) line = line.substring(3); + if(sourceLineCache == null) sourceLineCache = new java.util.HashMap(); + sourceLineCache.put(new Integer(pc),line); + return line; + } catch(IOException e) { + return null; + } + } + + public class DebugShutdownHook implements Runnable { + public void run() { + int pc = Interpreter.this.pc; + if(getState() == RUNNING) + System.err.print("\nCPU Executing " + toHex(pc) + ": " + sourceLine(pc) + "\n"); + } + } + + public static void main(String[] argv) throws Exception { + String image = argv[0]; + Interpreter emu = new Interpreter(image); + java.lang.Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook())); + int status = emu.run(argv); + System.err.println("Exit status: " + status); + System.exit(status); + } +} diff --git a/src/org/xwt/mips/JavaSourceCompiler.java b/src/org/xwt/mips/JavaSourceCompiler.java new file mode 100644 index 0000000..5bf7e5d --- /dev/null +++ b/src/org/xwt/mips/JavaSourceCompiler.java @@ -0,0 +1,933 @@ +package org.xwt.mips; + +import java.util.*; +import java.io.*; +import org.xwt.mips.util.SeekableData; + +public class JavaSourceCompiler extends Compiler { + /** Stores the "case r XXX: ... run_YYYY();" blocks generated by the emitText method/ */ + private StringBuffer runs = new StringBuffer(); + /** Stores the "initData" and "cleadData" calls generated by the emitData and emitBSS methods */ + private StringBuffer inits = new StringBuffer(); + /** Stores lines to go in the class scope */ + private StringBuffer classLevel = new StringBuffer(); + + /** The stream to write the compiled output to */ + private PrintWriter out; + + /** Prints a blank line to the output stream */ + private void p() { out.println(); } + /** prints the given string (indented by indent*4 spaces) to the output stream */ + private void p(String s) { out.println(indents[indent] + s); } + private void pblock(StringBuffer sb) { out.print(sb.toString()); } + + /** Used by the p() method to add indentation */ + private int indent; + + private static String indents[] = new String[16]; + static { String s=""; for(int i=0;i>>" + methodShift+ ") {"); + indent++; + pblock(runs); + p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(this.pc&0xffffffffL,16) + \": r2: \" + r2);"); + indent--; p("}"); + indent--; p("}"); + indent--; p("}"); + p(); + + // Constructor + p("public " + className + "() {"); + indent++; + p("super(" + pageSize + "," + totalPages + "," + (fastMem?"false":"true") + ");"); + p("entryPoint = " + toHex(elf.header.entry) + ";"); + if(userInfo != null) { + p("userInfoBase=" + toHex(userInfo.addr) + ";"); + p("userInfoSize=" + userInfo.size + ";"); + } + p("gp = " + toHex(gp.addr) + ";"); + if(onePage) + p("brkAddr = " + toHex((highestAddr+4095)&~4095) + ";"); + else + p("brkAddr = " + toHex((highestAddr+pageSize-1)&~(pageSize-1)) + ";"); + pblock(inits); + p("state = INITIALIZED;"); + indent--; + p("}"); + p(); + + // main() function + p("public static void main(String[] args) throws Exception {"); + indent++; + p("" + className + " me = new " + className + "();"); + p("int status = me.run(\"" + fullClassName + "\",args);"); + if(runtimeStats) p("me.printStats();"); + p("System.exit(status);"); + indent--; + p("}"); + p(); + + // Runtime abstract methods + p("protected void _execute() throws ExecutionException { trampoline(); }"); + p(); + + p("protected void setCPUState(CPUState state) {"); + indent++; + for(int i=1;i<32;i++) p("r" + i + "=state.r[" + i + "];"); + for(int i=0;i<32;i++) p("f" + i + "=state.f[" + i + "];"); + p("hi=state.hi; lo=state.lo; fcsr=state.fcsr;"); + p("pc=state.pc;"); + indent--; + p("}"); + p("protected CPUState getCPUState() {"); + indent++; + p("CPUState state = new CPUState();"); + for(int i=1;i<32;i++) p("state.r[" + i + "]=r" + i+ ";"); + for(int i=0;i<32;i++) p("state.f[" + i + "]=f" + i +";"); + p("state.hi=hi; state.lo=lo; state.fcsr=fcsr;"); + p("state.pc=pc;"); + p("return state;"); + indent--; + p("}"); + p(); + + if(supportCall) { + p("private static final " + hashClass + " symbols = new " + hashClass + "();"); + p("static {"); + indent++; + ELF.Symbol[] symbols = elf.getSymtab().symbols; + for(int i=0;i>>methodShift) + ": " + methodName + "(); break; \n"); + p("private final void " + methodName + "() throws ExecutionException { /"+"* " + toHex(addr) + " - " + toHex(endOfMethod) + " *" + "/"); + indent++; + p("int addr, tmp;"); + p("for(;;) {"); + indent++; + p("switch(pc) {"); + indent++; + } + + private void endMethod() { endMethod(endOfMethod); } + private void endMethod(int lastAddr) { + if(startOfMethod == 0) return; + // FEATURE: We should be able to use if(!unreachable) here (i think) + // This isn't strictly necessary; its just here to work around unreachable code errors + p("case " + toHex(lastAddr) + ":"); + indent++; + p("pc=" + constant(lastAddr) + ";"); + leaveMethod(); + indent--; + if(debugCompiler) + p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16) + \" (got here from 0x\" + Long.toString(lastPC&0xffffffffL,16)+\")\");"); + else + p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16));"); + indent--; + p("}"); // end switch + p("/* NOT REACHED */"); + indent--; + p("}"); // end for + indent--; + p("}"); // end method + endOfMethod = startOfMethod = 0; + } + + private HashMap relativeAddrs = new HashMap(); + private String constant(int target) { + if(target >= 4096 && lessConstants) { + int n = target & ~1023; + String var = "N_" + toHex8(n); + if(relativeAddrs.get(new Integer(n)) == null) { + relativeAddrs.put(new Integer(n),Boolean.TRUE); + classLevel.append(indents[1] + "private static int " + var + " = " + toHex(n) + ";\n"); + } + return "(" + var + " + " + toHex(target - n) + ")"; + } else { + return toHex(target); + } + } + + private void branch(int pc, int target) { + if(debugCompiler) p("lastPC = " + toHex(pc) + ";"); + p("pc=" + constant(target) + ";"); + if(target == 0) + p("throw new ExecutionException(\"Branch to addr 0x0\");"); + else if((pc&methodMask) == (target&methodMask)) + p("continue;"); + else if(assumeTailCalls) + p("run_" + Long.toString((target&methodMask)&0xffffffffL, 16) + "(); return;"); + else + leaveMethod(); + } + + private void leaveMethod() { + p("return;"); + } + + private boolean textDone; + private void emitText(int addr, DataInputStream dis, int size) throws Exn,IOException { + if(textDone) throw new Exn("Multiple text segments"); + textDone = true; + + if((addr&3)!=0 || (size&3)!=0) throw new Exn("Section on weird boundaries"); + int count = size/4; + int nextInsn = dis.readInt(); + if(nextInsn == -1) throw new Error("Actually read -1 at " + toHex(addr)); + int insn; + + for(int i=0;i= endOfMethod) { endMethod(); startMethod(addr); } + if(jumpableAddresses==null || addr == startOfMethod || jumpableAddresses.contains(new Integer(addr))) { + p("case " + toHex(addr) + ":"); + unreachable = false; + } else if(unreachable) { + continue; + } else if(debugCompiler) { + p("/" + "* pc = " + toHex(addr) + "*" + "/"); + } + indent++; + emitInstruction(addr,insn,nextInsn); + indent--; + } + endMethod(addr); + p(); + dis.close(); + } + + private int initDataCount = 0; + private void emitData(int addr, DataInputStream dis, int size, boolean readOnly) throws Exn,IOException { + if((addr&3)!=0 || (size&3)!=0) throw new Exn("Data section on weird boundaries"); + int last = addr + size; + while(addr < last) { + int segSize = Math.min(size,28000); // must be a multiple of 56 + StringBuffer sb = new StringBuffer(); + for(int i=0;i>>(7*(7-j)))&0x7f); + if(c=='\n') sb.append("\\n"); + else if(c=='\r') sb.append("\\r"); + else if(c=='\\') sb.append("\\\\"); + else if(c=='"') sb.append("\\\""); + else if(c >= 32 && c <= 126) sb.append(c); + else sb.append("\\" + toOctal3(c)); + } + } + String varname = "_data" + (++initDataCount); + p("private static final int[] " + varname + " = decodeData(\"" + sb.toString() + "\"," + toHex(segSize/4) + ");"); + inits.append(indents[2] + "initPages(" + varname +"," + toHex(addr) + "," + (readOnly?"true":"false") + ");\n"); + addr += segSize; + size -= segSize; + } + dis.close(); + } + + private void emitBSS(int addr, int size) throws Exn { + if((addr&3)!=0) throw new Exn("BSS section on weird boundaries"); + size = (size+3)&~3; + int count = size/4; + inits.append(indents[2] + "clearPages(" + toHex(addr) + "," + toHex(count) + ");\n"); + } + + // True if the current code path is unreachable (any instruction with a case statement is reachable) + private boolean unreachable = false; + + private void emitInstruction(int pc, int insn, int nextInsn) throws IOException,Exn { + if(insn == -1) throw new Error("insn is -1"); + + int op = (insn >>> 26) & 0xff; // bits 26-31 + int rs = (insn >>> 21) & 0x1f; // bits 21-25 + int rt = (insn >>> 16) & 0x1f; // bits 16-20 + int ft = (insn >>> 16) & 0x1f; + int rd = (insn >>> 11) & 0x1f; // bits 11-15 + int fs = (insn >>> 11) & 0x1f; + int shamt = (insn >>> 6) & 0x1f; // bits 6-10 + int fd = (insn >>> 6) & 0x1f; + int subcode = insn & 0x3f; // bits 0-5 + + int jumpTarget = (insn & 0x03ffffff); // bits 0-25 + int unsignedImmediate = insn & 0xffff; + int signedImmediate = (insn << 16) >> 16; + int branchTarget = signedImmediate; + + int tmp; // temporaries + + //if(pc%64==0) p("System.err.println(\"Executing: " + toHex(pc) + "\");"); + //p("/" + "*" + (pc == -1 ? "Delay Slot" : toHex(pc)) + " *" + "/ "); + if(pc==-1) p("/" + "* Next insn is delay slot *" + "/ "); + + if(runtimeStats && op != 0) p("inc(\"opcode: " + op + "\");"); + switch(op) { + case 0: { + if(runtimeStats && insn != 0) p("inc(\"opcode: 0/" + subcode + "\");"); + switch(subcode) { + case 0: // SLL + if(insn != 0) + p( "r"+rd+" = r"+rt+" << "+shamt+";"); + break; + case 2: // SRL + p( "r"+rd+" = r"+rt+" >>> "+shamt+";"); + break; + case 3: // SRA + p( "r"+rd+" = r"+rt+" >> "+shamt+";"); + break; + case 4: // SLLV + p( "r"+rd+" = r"+rt+" << (r"+rs+"&0x1f);"); + break; + case 6: // SRLV + p( "r"+rd+" = r"+rt+" >>> (r"+rs+"&0x1f);"); + break; + case 7: // SRAV + p( "r"+rd+" = r"+rt+" >> (r"+rs+"&0x1f);"); + break; + case 8: // JR + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + if(debugCompiler) p("lastPC = " + toHex(pc) + ";"); + p("pc=r" + rs + ";"); + leaveMethod(); + unreachable = true; + break; + case 9: // JALR + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + if(debugCompiler) p("lastPC = " + toHex(pc) + ";"); + p("pc=r" + rs + ";"); + p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); + leaveMethod(); + unreachable = true; + break; + case 12: // SYSCALL + p("pc = " + toHex(pc) + ";"); + p( "r"+V0+" = syscall(r"+V0+",r"+A0+",r"+A1+",r"+A2+",r"+A3+");"); + p("if (state != RUNNING) {"); + indent++; + p("pc = " + toHex(pc+4) + ";"); + leaveMethod(); + indent--; + p("}"); + break; + case 13: // BREAK + p( "throw new ExecutionException(\"Break\");"); + break; + case 16: // MFHI + p( "r"+rd+" = hi;"); + break; + case 17: // MTHI + p( "hi = r"+rs+";"); + break; + case 18: // MFLO + p( "r"+rd+" = lo;"); + break; + case 19: // MTLO + p( "lo = r"+rs+";"); + break; + case 24: // MULT + p( "{ long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " + + "hi = (int) (hilo >>> 32); " + + "lo = (int) hilo; }"); + break; + case 25: // MULTU + p( "{ long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " + + "hi = (int) (hilo >>> 32); " + + "lo = (int) hilo; } "); + break; + case 26: // DIV + p( "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";"); + break; + case 27: // DIVU + p("if(r"+rt+"!=0) {"); + p( "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " + + "lo = (int)((r"+rs+" & 0xffffffffL) / (r"+rt+" & 0xffffffffL));"); + p("}"); + break; + case 32: // ADD + throw new Exn("ADD (add with oveflow trap) not suported"); + /*This must trap on overflow + p( "r"+rd+" = r"+rs+" + r"+rt+";"); + break;*/ + case 33: // ADDU + p( "r"+rd+" = r"+rs+" + r"+rt+";"); + break; + case 34: // SUB + throw new Exn("SUB (add with oveflow trap) not suported"); + /*This must trap on overflow + p( "r"+rd+" = r"+rs+" - r"+rt+";"); + break;*/ + case 35: // SUBU + p( "r"+rd+" = r"+rs+" - r"+rt+";"); + break; + case 36: // AND + p( "r"+rd+" = r"+rs+" & r"+rt+";"); + break; + case 37: // OR + p( "r"+rd+" = r"+rs+" | r"+rt+";"); + break; + case 38: // XOR + p( "r"+rd+" = r"+rs+" ^ r"+rt+";"); + break; + case 39: // NOR + p( "r"+rd+" = ~(r"+rs+" | r"+rt+");"); + break; + case 42: // SLT + p( "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;"); + break; + case 43: // SLTU + p( "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;"); + break; + default: + throw new RuntimeException("Illegal instruction 0/" + subcode); + } + break; + } + case 1: { + switch(rt) { + case 0: // BLTZ + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " < 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 1: // BGEZ + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " >= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 16: // BLTZAL + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " < 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 17: // BGEZAL + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " >= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + default: + throw new RuntimeException("Illegal Instruction 1/" + rt); + } + break; + } + case 2: { // J + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + branch(pc,(pc&0xf0000000)|(jumpTarget << 2)); + unreachable = true; + break; + } + case 3: { // JAL + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + int target = (pc&0xf0000000)|(jumpTarget << 2); + emitInstruction(-1,nextInsn,-1); + if(optimizedMemcpy && (target == memcpy || target == memset)) { + if(target == memcpy) + p("memcpy(r4,r5,r6);"); + else if(target == memset) + p("memset(r4,r5,r6);"); + p("r2 = r4;"); + branch(pc,pc+8); + } else { + p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc, target); + } + unreachable = true; + break; + } + case 4: // BEQ + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " == r" + rt + ") {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 5: // BNE + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " != r" + rt + ") {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 6: //BLEZ + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " <= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 7: //BGTZ + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " > 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + case 8: // ADDI + p( "r"+rt+" = r"+rs+" + "+signedImmediate +";"); + break; + case 9: // ADDIU + p( "r"+rt+" = r"+rs+" + "+signedImmediate+";"); + break; + case 10: // SLTI + p( "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;"); + break; + case 11: // SLTIU + p( "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;"); + break; + case 12: // ANDI + p( "r"+rt+" = r"+rs+" & "+unsignedImmediate+";"); + break; + case 13: // ORI + p( "r"+rt+" = r"+rs+" | "+unsignedImmediate+";"); + break; + case 14: // XORI + p( "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";"); + break; + case 15: // LUI + p( "r"+rt+" = "+unsignedImmediate+" << 16;"); + break; + case 16: + throw new Exn("TLB/Exception support not implemented"); + case 17: { // FPU + switch(rs) { + case 0: // MFC.1 + p( "r"+rt+" = f"+rd+";"); + break; + case 2: // CFC.1 + if(fs != 31) throw new Exn("FCR " + fs + " unavailable"); + p( "r"+rt+" = fcsr;"); + break; + case 4: // MTC.1 + p( "f"+rd+" = r"+rt+";"); + break; + case 6: // CTC.1 + if(fs != 31) throw new Exn("FCR " + fs + " unavailable"); + p( "fcsr = r"+rt+";"); + break; + case 8: {// BC1F, BC1T + tmp = (insn>>>16)&1; + p("if(((fcsr&0x800000)!=0) == (" + tmp + "!=0)) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); + break; + } + case 16: { // Single + switch(subcode) { + case 0: // ADD.S + p(setFloat(fd,getFloat(fs)+"+"+getFloat(ft))); + break; + case 1: // SUB.S + p(setFloat(fd,getFloat(fs)+"-"+getFloat(ft))); + break; + case 2: // MUL.S + p(setFloat(fd,getFloat(fs)+"*"+getFloat(ft))); + break; + case 3: // DIV.S + p(setFloat(fd,getFloat(fs)+"/"+getFloat(ft))); + break; + case 5: // ABS.S + p(setFloat(fd,"Math.abs("+getFloat(fs)+")")); + break; + case 6: // MOV.S + p("f"+fd+" = f"+fs+"; // MOV.S"); + break; + case 7: // NEG.S + p(setFloat(fd,"-"+getFloat(fs))); + break; + case 33: // CVT.D.S + p(setDouble(fd,"(float)"+getFloat(fs))); + break; + case 36: // CVT.W.D + p("switch(fcsr & 3) {"); + indent++; + p("case 0: f"+fd+" = (int)Math.floor("+getFloat(fs)+"+0.5); break; // Round to nearest"); + p("case 1: f"+fd+" = (int)"+getFloat(fs)+"; break; // Round towards zero"); + p("case 2: f"+fd+" = (int)Math.ceil("+getFloat(fs)+"); break; // Round towards plus infinity"); + p("case 3: f"+fd+" = (int)Math.floor("+getFloat(fs)+"); break; // Round towards minus infinity"); + indent--; + p("}"); + break; + case 50: // C.EQ.S + p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"=="+getFloat(ft)+") ? 0x800000 : 0x000000);"); + break; + case 60: // C.LT.S + p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"<"+getFloat(ft)+") ? 0x800000 : 0x000000);"); + break; + case 62: // C.LE.S + p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"<="+getFloat(ft)+") ? 0x800000 : 0x000000);"); + break; + default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); + } + break; + } + case 17: { // Double + switch(subcode) { + case 0: // ADD.D + p(setDouble(fd,getDouble(fs)+"+"+getDouble(ft))); + break; + case 1: // SUB.D + p(setDouble(fd,getDouble(fs)+"-"+getDouble(ft))); + break; + case 2: // MUL.D + p(setDouble(fd,getDouble(fs)+"*"+getDouble(ft))); + break; + case 3: // DIV.D + p(setDouble(fd,getDouble(fs)+"/"+getDouble(ft))); + break; + case 5: // ABS.D + p(setDouble(fd,"Math.abs("+getDouble(fs)+")")); + break; + case 6: // MOV.D + p("f"+fd+" = f"+fs+";"); + p("f"+(fd+1)+" = f"+(fs+1)+";"); + break; + case 7: // NEG.D + p(setDouble(fd,"-"+getDouble(fs))); + break; + case 32: // CVT.S.D + p(setFloat(fd,"(float)"+getDouble(fs))); + break; + case 36: // CVT.W.D + p("switch(fcsr & 3) {"); + indent++; + p("case 0: f"+fd+" = (int)Math.floor("+getDouble(fs)+"+0.5); break; // Round to nearest"); + p("case 1: f"+fd+" = (int)"+getDouble(fs)+"; break; // Round towards zero"); + p("case 2: f"+fd+" = (int)Math.ceil("+getDouble(fs)+"); break; // Round towards plus infinity"); + p("case 3: f"+fd+" = (int)Math.floor("+getDouble(fs)+"); break; // Round towards minus infinity"); + indent--; + p("}"); + break; + case 50: // C.EQ.D + p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"=="+getDouble(ft)+") ? 0x800000 : 0x000000);"); + break; + case 60: // C.LT.D + p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"<"+getDouble(ft)+") ? 0x800000 : 0x000000);"); + break; + case 62: // C.LE.D + p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"<="+getDouble(ft)+") ? 0x800000 : 0x000000);"); + break; + default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); + } + break; + } + case 20: { // Integer + switch(subcode) { + case 32: // CVT.S.W + p(" // CVS.S.W"); + p(setFloat(fd,"((float)f"+fs+")")); + break; + case 33: // CVT.D.W + p(setDouble(fd,"((double)f"+fs+")")); + break; + default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); + } + break; + } + default: + throw new Exn("Invalid Instruction 17/" + rs); + } + break; + } + case 18: case 19: + throw new Exn("coprocessor 2 and 3 instructions not available"); + case 32: { // LB + if(runtimeStats) p("inc(\"LB\");"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp>>>(((~addr)&3)<<3)) & 0xff;"); + p("if((tmp&0x80)!=0) tmp |= 0xffffff00; /* sign extend */"); + p("r"+rt+" = tmp;"); + break; + } + case 33: { // LH + if(runtimeStats) p("inc(\"LH\");"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp>>>(((~addr)&2)<<3)) & 0xffff;"); + p("if((tmp&0x8000)!=0) tmp |= 0xffff0000; /* sign extend */"); + p("r"+rt+" = tmp;"); + break; + } + case 34: { // LWL; + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("r" + rt + " = (r"+rt+"&(0x00ffffff>>>(((~addr)&3)<<3)))|(tmp<<((addr&3)<<3));"); + break; + /*p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: r"+rt+" = (r"+rt+"&0x00000000)|(tmp<< 0); break;"); + p("case 1: r"+rt+" = (r"+rt+"&0x000000ff)|(tmp<< 8); break;"); + p("case 2: r"+rt+" = (r"+rt+"&0x0000ffff)|(tmp<<16); break;"); + p("case 3: r"+rt+" = (r"+rt+"&0x00ffffff)|(tmp<<24); break;"); + indent--; + p("}"); + break;*/ + } + case 35: // LW + if(runtimeStats) p("inc(\"LW\");"); + memRead("r" + rs +"+"+signedImmediate,"r"+rt); + break; + case 36: { // LBU + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp>>>(((~addr)&3)<<3)) & 0xff;"); + p("r"+rt+" = tmp;"); + break; + } + case 37: { // LHU + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp>>>(((~addr)&2)<<3)) & 0xffff;"); + p("r"+rt+" = tmp;"); + break; + } + case 38: { // LWR + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("r" + rt + " = (r"+rt+"&(0xffffff00<<((addr&3)<<3)))|(tmp>>>(((~addr)&3)<<3));"); + break; + + /*p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: r"+rt+" = (r"+rt+"&0xffffff00)|(tmp>>>24); break;"); + p("case 1: r"+rt+" = (r"+rt+"&0xffff0000)|(tmp>>>16); break;"); + p("case 2: r"+rt+" = (r"+rt+"&0xff000000)|(tmp>>> 8); break;"); + p("case 3: r"+rt+" = (r"+rt+"&0x00000000)|(tmp>>> 0); break;"); + indent--; + p("}"); + break;*/ + + } + case 40: { // SB + if(runtimeStats) p("inc(\"SB\");"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp&~(0xff000000>>>((addr&3)<<3)))|((r"+rt+"&0xff)<<(((~addr)&3)<<3));"); + memWrite("addr","tmp"); + break; + } + case 41: { // SH + if(runtimeStats) p("inc(\"SH\");"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp&(0xffff<<((addr&2)<<3)))|((r" + rt + "&0xffff)<<(((~addr)&2)<<3));"); + memWrite("addr","tmp"); + break; + } + case 42: { // SWL + p(" // SWL"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp&(0xffffff00<<(((~addr)&3)<<3)))|(r"+rt+">>>((addr&3)<<3));"); + memWrite("addr","tmp"); + break; + } + case 43: // SW + if(runtimeStats) p("inc(\"SW\");"); + memWrite("r"+rs+"+"+signedImmediate,"r" + rt); + break; + case 46: { // SWR + p(" // SWR"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr","tmp"); + p("tmp = (tmp&(0x00ffffff>>>((addr&3)<<3)))|(r"+rt+"<<(((~addr)&3)<<3));"); + memWrite("addr","tmp"); + break; + } + // FEATURE: Need to be atomic if threads + case 48: // LWC0/LL + memRead("r"+rs+"+"+signedImmediate,"r"+rt); + break; + case 49: // LWC1 + memRead("r"+rs+"+"+signedImmediate,"f"+rt); + break; + // FEATURE: Needs to be atomic if threads + case 56: // SWC1/SC + memWrite("r"+rs+"+"+signedImmediate,"r"+rt); + p("r" + rt + "=1;"); + break; + case 57: // SWC1 + memWrite("r"+rs+"+"+signedImmediate,"f"+rt); + break; + default: + throw new Exn("Invalid Instruction: " + op + " at " + toHex(pc)); + } + } + + // Helper functions for emitText + // NOTE: memWrite and memRead MUST discard the last two bits of addr + private void memWrite(String addr, String target) { + if(nullPointerCheck) p("nullPointerCheck(" + addr + ");"); + if(onePage) + p("page[(" + addr + ")>>>2] = " + target + ";"); + else if(fastMem) + p("writePages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"] = " + target + ";"); + else + p("unsafeMemWrite(" + addr + "," + target + ");"); + } + private void memRead(String addr, String target) { + if(nullPointerCheck) p("nullPointerCheck(" + addr + ");"); + if(onePage) + p(target + "= page[(" + addr + ")>>>2];"); + else if(fastMem) + p(target + " = readPages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"];"); + else + p(target + " = unsafeMemRead(" + addr + ");"); + } + private static String getFloat(int r) { return "(Float.intBitsToFloat(f"+r+"))"; } + private static String getDouble(int r) { + return "(Double.longBitsToDouble(((f"+(r+1)+"&0xffffffffL) << 32) | (f"+r+"&0xffffffffL)))"; + } + private static String setFloat(int r, String expr) { return "f"+r+"=Float.floatToRawIntBits("+expr+");"; } + private static String setDouble(int r, String expr) { + return "{ long l = Double.doubleToLongBits("+expr+"); "+ + "f"+(r+1)+" = (int)(l >>> 32); f"+r+" = (int)l; }"; + } +} + \ No newline at end of file diff --git a/src/org/xwt/mips/Registers.java b/src/org/xwt/mips/Registers.java new file mode 100644 index 0000000..14b2825 --- /dev/null +++ b/src/org/xwt/mips/Registers.java @@ -0,0 +1,42 @@ +package org.xwt.mips; + +interface Registers { + // Register Names + public final static int ZERO = 0; // Immutable, hardwired to 0 + public final static int AT = 1; // Reserved for assembler + public final static int K0 = 26; // Reserved for kernel + public final static int K1 = 27; // Reserved for kernel + public final static int GP = 28; // Global pointer (the middle of .sdata/.sbss) + public final static int SP = 29; // Stack pointer + public final static int FP = 30; // Frame Pointer + public final static int RA = 31; // Return Address + + // Return values (caller saved) + public final static int V0 = 2; + public final static int V1 = 3; + // Argument Registers (caller saved) + public final static int A0 = 4; + public final static int A1 = 5; + public final static int A2 = 6; + public final static int A3 = 7; + // Temporaries (caller saved) + public final static int T0 = 8; + public final static int T1 = 9; + public final static int T2 = 10; + public final static int T3 = 11; + public final static int T4 = 12; + public final static int T5 = 13; + public final static int T6 = 14; + public final static int T7 = 15; + public final static int T8 = 24; + public final static int T9 = 25; + // Saved (callee saved) + public final static int S0 = 16; + public final static int S1 = 17; + public final static int S2 = 18; + public final static int S3 = 19; + public final static int S4 = 20; + public final static int S5 = 21; + public final static int S6 = 22; + public final static int S7 = 23; +} diff --git a/src/org/xwt/mips/Runtime.java b/src/org/xwt/mips/Runtime.java new file mode 100644 index 0000000..6a5c4b6 --- /dev/null +++ b/src/org/xwt/mips/Runtime.java @@ -0,0 +1,1256 @@ +// Copyright 2003 Brian Alliet +// Based on org.xwt.imp.MIPS by Adam Megacz +// Portions Copyright 2003 Adam Megacz + +package org.xwt.mips; + +import org.xwt.mips.util.*; +import java.io.*; +import java.util.Arrays; + +// FEATURE: Look over the public API, make sure we're exposing a bare minimum +// (we might make this an interface in the future) + +public abstract class Runtime implements UsermodeConstants,Registers { + /** Pages are 4k in size */ + protected final int PAGE_SIZE; + protected final int PAGE_WORDS; + protected final int PAGE_SHIFT; + protected final int TOTAL_PAGES; + /** This is the upper limit of the pages allocated by the sbrk() syscall. */ + protected final int BRK_LIMIT; + protected final int STACK_BOTTOM; + + /** This is the maximum size of command line arguments */ + public final static int ARGS_MAX = 1024*1024; + + /** True if we allow empty pages (_emptyPage) to exist in memory. + Empty pages are pages which are allocated by the program but do not contain any + data yet (they are all 0s). If empty pages are allowed subclasses must always + access main memory with the memRead and memWrite functions */ + private final boolean allowEmptyPages; + /** the "empty page" */ + private final static int[] _emptyPage = new int[0]; + + protected final static boolean isEmptyPage(int[] page) { return page == _emptyPage; } + + /** Returns a new empty page (_emptyPage is empty pages are enabled or a new zero'd page) */ + private final int[] emptyPage() { return allowEmptyPages ? _emptyPage : new int[PAGE_WORDS]; } + + /** Readable main memory pages */ + protected final int[][] readPages; + /** Writable main memory pages. + If the page is writable writePages[x] == readPages[x]; if not writePages[x] == null. */ + protected final int[][] writePages; + + /** The current break between the heap and unallocated memory */ + protected int brkAddr; + + /** The program's entry point */ + protected int entryPoint; + + /** The location of the _user_info block (or 0 is there is none) */ + protected int userInfoBase; + protected int userInfoSize; + + /** The location of the global pointer */ + protected int gp; + + /** When the process started */ + private long startTime; + + /** State constant: There is no program loaded in memory */ + public final static int UNINITIALIZED = 0; + /** Text/Data loaded in memory */ + public final static int INITIALIZED = 1; + /** Program is executing instructions */ + public final static int RUNNING = 2; + /** Prgram has been started but is paused */ + public final static int PAUSED = 3; + /** Program is executing a callJava() method */ + public final static int CALLJAVA = 4; + /** Program has exited (it cannot currently be restarted) */ + public final static int DONE = 5; + + /** The current state (UNINITIALIZED, INITIALIZED, RUNNING, PAUSED, or DONE) */ + protected int state = UNINITIALIZED; + /** @see Runtime#state state */ + public final int getState() { return state; } + + /** The exit status if the process (only valid if state==DONE) + @see Runtime#state */ + protected int exitStatus; + public ExecutionException exitException; + + /** Maximum number of open file descriptors */ + final static int OPEN_MAX = 256; + /** Table containing all open file descriptors. (Entries are null if the fd is not in use */ + FD[] fds = new FD[OPEN_MAX]; + + /** Temporary buffer for read/write operations */ + private byte[] _byteBuf = null; + /** Max size of temporary buffer + @see Runtime#_byteBuf */ + private final static int MAX_CHUNK = 15*1024*1024; + + /** Subclasses should actually execute program in this method. They should continue + executing until state != RUNNING. Only syscall() can modify state. It is safe + to only check the state attribute after a call to syscall() */ + protected abstract void _execute() throws ExecutionException; + + /** Subclasses should return the address of the symbol symbol or -1 it it doesn't exits in this method + This method is only required if the call() function is used */ + protected int lookupSymbol(String symbol) { return -1; } + + /** Subclasses should returns a CPUState object representing the cpu state */ + protected abstract CPUState getCPUState(); + + /** Subclasses should set the CPUState to the state held in state */ + protected abstract void setCPUState(CPUState state); + + static void checkPageSize(int pageSize, int totalPages) throws IllegalArgumentException { + if(pageSize < 256) throw new IllegalArgumentException("pageSize too small"); + if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize must be a power of two"); + if((totalPages&(totalPages-1)) != 0) throw new IllegalArgumentException("totalPages must be a power of two"); + if(totalPages != 1 && totalPages < 256) throw new IllegalArgumentException("totalPages too small"); + if(totalPages * pageSize < 4*1024*1024) throw new IllegalArgumentException("total memory too small (" + totalPages + "*" + pageSize + ")"); + } + + protected Runtime(int pageSize, int totalPages, boolean allowEmptyPages) { + this.allowEmptyPages = allowEmptyPages; + + checkPageSize(pageSize,totalPages); + + PAGE_SIZE = pageSize; + PAGE_WORDS = pageSize>>>2; + int pageShift = 0; + while(pageSize>>>pageShift != 1) pageShift++; + PAGE_SHIFT = pageShift; + + TOTAL_PAGES = totalPages; + + readPages = new int[TOTAL_PAGES][]; + writePages = new int[TOTAL_PAGES][]; + + if(TOTAL_PAGES == 1) { + readPages[0] = writePages[0] = new int[PAGE_WORDS]; + BRK_LIMIT = STACK_BOTTOM = 0; + } else { + int stackPages = max(TOTAL_PAGES>>>8,(1024*1024)>>>PAGE_SHIFT); + STACK_BOTTOM = (TOTAL_PAGES - stackPages) * PAGE_SIZE; + // leave some unmapped pages between the stack and the heap + BRK_LIMIT = STACK_BOTTOM - 4*PAGE_SIZE; + + for(int i=0;isrc to addr initializing uninitialized pages if required. + Newly initalized pages will be marked read-only if ro is set */ + protected final void initPages(int[] src, int addr, boolean ro) { + for(int i=0;i>> PAGE_SHIFT; + int start = (addr&(PAGE_SIZE-1))>>2; + int elements = min(PAGE_WORDS-start,src.length-i); + if(readPages[page]==null) { + initPage(page,ro); + } else if(!ro) { + if(writePages[page] == null) writePages[page] = readPages[page]; + } + System.arraycopy(src,i,readPages[page],start,elements); + i += elements; + addr += elements*4; + } + } + + /** Initialize words of pages starting at addr to 0 */ + protected final void clearPages(int addr, int words) { + for(int i=0;i>> PAGE_SHIFT; + int start = (addr&(PAGE_SIZE-1))>>2; + int elements = min(PAGE_WORDS-start,words-i); + if(readPages[page]==null) { + readPages[page] = writePages[page] = emptyPage(); + } else { + if(writePages[page] == null) writePages[page] = readPages[page]; + for(int j=start;jlength bytes from the processes memory space starting at + addr INTO a java byte array a */ + public final void copyin(int addr, byte[] buf, int count) throws ReadFaultException { + int x=0; + if((addr&3)!=0) { + int word = memRead(addr&~3); + switch(addr&3) { + case 1: buf[x++] = (byte)((word>>>16)&0xff); if(--count==0) break; + case 2: buf[x++] = (byte)((word>>> 8)&0xff); if(--count==0) break; + case 3: buf[x++] = (byte)((word>>> 0)&0xff); if(--count==0) break; + } + addr = (addr&~3)+4; + } + if((count&~3) != 0) { + int c = count>>>2; + int a = addr>>>2; + while(c != 0) { + int[] page = readPages[a >>> (PAGE_SHIFT-2)]; + if(page == null) throw new ReadFaultException(a<<2); + int index = a&(PAGE_WORDS-1); + int n = min(c,PAGE_WORDS-index); + if(page != _emptyPage) { + for(int i=0;i>>24)&0xff); buf[x+1] = (byte)((word>>>16)&0xff); + buf[x+2] = (byte)((word>>> 8)&0xff); buf[x+3] = (byte)((word>>> 0)&0xff); + } + } + a += n; c -=n; + } + addr = a<<2; count &=3; + } + if(count != 0) { + int word = memRead(addr); + switch(count) { + case 3: buf[x+2] = (byte)((word>>>8)&0xff); + case 2: buf[x+1] = (byte)((word>>>16)&0xff); + case 1: buf[x+0] = (byte)((word>>>24)&0xff); + } + } + } + + /** Copies length bytes OUT OF the java array a into the processes memory + space at addr */ + public final void copyout(byte[] buf, int addr, int count) throws FaultException { + int x=0; + if((addr&3)!=0) { + int word = memRead(addr&~3); + switch(addr&3) { + case 1: word = (word&0xff00ffff)|((buf[x++]&0xff)<<16); if(--count==0) break; + case 2: word = (word&0xffff00ff)|((buf[x++]&0xff)<< 8); if(--count==0) break; + case 3: word = (word&0xffffff00)|((buf[x++]&0xff)<< 0); if(--count==0) break; + } + memWrite(addr&~3,word); + addr += x; + } + if((count&~3) != 0) { + int c = count>>>2; + int a = addr>>>2; + while(c != 0) { + int[] page = writePages[a >>> (PAGE_SHIFT-2)]; + if(page == null) throw new WriteFaultException(a<<2); + if(page == _emptyPage) page = initPage(a >>> (PAGE_SHIFT-2)); + int index = a&(PAGE_WORDS-1); + int n = min(c,PAGE_WORDS-index); + for(int i=0;i>2; + int s = src>>>2; + int d = dst>>>2; + while(c != 0) { + int[] srcPage = readPages[s>>>(PAGE_SHIFT-2)]; + if(srcPage == null) throw new ReadFaultException(s<<2); + int[] dstPage = writePages[d>>>(PAGE_SHIFT-2)]; + if(dstPage == null) throw new WriteFaultException(d<<2); + int srcIndex = (s&(PAGE_WORDS-1)); + int dstIndex = (d&(PAGE_WORDS-1)); + int n = min(c,PAGE_WORDS-max(srcIndex,dstIndex)); + if(srcPage != _emptyPage) { + if(dstPage == _emptyPage) dstPage = initPage(d>>>(PAGE_SHIFT-2)); + System.arraycopy(srcPage,srcIndex,dstPage,dstIndex,n); + } else if(srcPage == _emptyPage && dstPage != _emptyPage) { + Arrays.fill(dstPage,dstIndex,dstIndex+n,0); + } + s += n; d += n; c -= n; + } + src = s<<2; dst = d<<2; count&=3; + } + if(count != 0) { + int word1 = memRead(src); + int word2 = memRead(dst); + switch(count) { + case 1: memWrite(dst,(word1&0xff000000)|(word2&0x00ffffff)); break; + case 2: memWrite(dst,(word1&0xffff0000)|(word2&0x0000ffff)); break; + case 3: memWrite(dst,(word1&0xffffff00)|(word2&0x000000ff)); break; + } + } + } else { + while(count > 0) { + int n = min(count,MAX_CHUNK); + byte[] buf = byteBuf(n); + copyin(src,buf,n); + copyout(buf,dst,n); + count -= n; src += n; dst += n; + } + } + } + + public final void memset(int addr, int ch, int count) throws FaultException { + int fourBytes = ((ch&0xff)<<24)|((ch&0xff)<<16)|((ch&0xff)<<8)|((ch&0xff)<<0); + if((addr&3)!=0) { + int word = memRead(addr&~3); + switch(addr&3) { + case 1: word = (word&0xff00ffff)|((ch&0xff)<<16); if(--count==0) break; + case 2: word = (word&0xffff00ff)|((ch&0xff)<< 8); if(--count==0) break; + case 3: word = (word&0xffffff00)|((ch&0xff)<< 0); if(--count==0) break; + } + memWrite(addr&~3,word); + addr = (addr&~3)+4; + } + if((count&~3) != 0) { + int c = count>>2; + int a = addr>>>2; + while(c != 0) { + int[] page = readPages[a>>>(PAGE_SHIFT-2)]; + if(page == null) throw new WriteFaultException(a<<2); + int index = (a&(PAGE_WORDS-1)); + int n = min(c,PAGE_WORDS-index); + if(page != _emptyPage || ch != 0) { + if(page == _emptyPage) page = initPage(a>>>(PAGE_SHIFT-2)); + Arrays.fill(page,index,index+n,fourBytes); + } + a += n; c -= n; + } + addr = a<<2; count&=3; + } + if(count != 0) { + int word = memRead(addr); + switch(count) { + case 1: word = (word&0x00ffffff)|(fourBytes&0xff000000); break; + case 2: word = (word&0x0000ffff)|(fourBytes&0xffff0000); break; + case 3: word = (word&0x000000ff)|(fourBytes&0xffffff00); break; + } + memWrite(addr,word); + } + } + + /** Read a word from the processes memory at addr */ + public final int memRead(int addr) throws ReadFaultException { + if((addr & 3) != 0) throw new ReadFaultException(addr); + return unsafeMemRead(addr); + } + + protected final int unsafeMemRead(int addr) throws ReadFaultException { + int page = addr >>> PAGE_SHIFT; + int entry = (addr >>> 2) & (PAGE_WORDS-1); + try { + return readPages[page][entry]; + } catch(ArrayIndexOutOfBoundsException e) { + if(page < 0) throw e; // should never happen + if(page >= readPages.length) throw new ReadFaultException(addr); + if(readPages[page] != _emptyPage) throw e; // should never happen + initPage(page); + return 0; + } catch(NullPointerException e) { + throw new ReadFaultException(addr); + } + } + + /** Writes a word to the processes memory at addr */ + public final void memWrite(int addr, int value) throws WriteFaultException { + if((addr & 3) != 0) throw new WriteFaultException(addr); + unsafeMemWrite(addr,value); + } + + protected final void unsafeMemWrite(int addr, int value) throws WriteFaultException { + int page = addr >>> PAGE_SHIFT; + int entry = (addr>>>2)&(PAGE_WORDS-1); + try { + writePages[page][entry] = value; + } catch(ArrayIndexOutOfBoundsException e) { + if(page < 0) throw e;// should never happen + if(page >= writePages.length) throw new WriteFaultException(addr); + if(readPages[page] != _emptyPage) throw e; // should never happen + initPage(page); + writePages[page][entry] = value; + } catch(NullPointerException e) { + throw new WriteFaultException(addr); + } + } + + /** Created a new non-empty writable page at page number page */ + private final int[] initPage(int page) { return initPage(page,false); } + /** Created a new non-empty page at page number page. If ro is set the page will be read-only */ + private final int[] initPage(int page, boolean ro) { + int[] buf = new int[PAGE_WORDS]; + writePages[page] = ro ? null : buf; + readPages[page] = buf; + return buf; + } + + /** Returns the exit status of the process. (only valid if state == DONE) + @see Runtime#state */ + public final int exitStatus() { + if(state != DONE) throw new IllegalStateException("exitStatus() called in an inappropriate state"); + return exitStatus; + } + + private int addStringArray(String[] strings, int topAddr) { + int count = strings.length; + int total = 0; /* null last table entry */ + for(int i=0;i= ARGS_MAX) throw new IllegalArgumentException("arguments/environ too big"); + total += (count+1)*4; + int start = (topAddr - total)&~3; + int addr = start + (count+1)*4; + int[] table = new int[count+1]; + try { + for(int i=0;iindex in the _user_info table to word + * The user_info table is a chunk of memory in the program's memory defined by the + * symbol "user_info". The compiler/interpreter automatically determine the size + * and location of the user_info table from the ELF symbol table. setUserInfo and + * getUserInfo are used to modify the words in the user_info table. */ + public void setUserInfo(int index, int word) { + if(index < 0 || index >= userInfoSize/4) throw new IndexOutOfBoundsException("setUserInfo called with index >= " + (userInfoSize/4)); + try { + memWrite(userInfoBase+index*4,word); + } catch(FaultException e) { throw new Error("should never happen: " + e); } + } + + /** Returns the word in the _user_info table entry index + @see Runtime#setUserInfo(int,int) setUserInfo */ + public int getUserInfo(int index) { + if(index < 0 || index >= userInfoSize/4) throw new IndexOutOfBoundsException("setUserInfo called with index >= " + (userInfoSize/4)); + try { + return memRead(userInfoBase+index*4); + } catch(FaultException e) { throw new Error("should never happen: " + e); } + } + + /** Calls _execute() (subclass's execute()) and catches exceptions */ + private void __execute() { + try { + _execute(); + } catch(FaultException e) { + e.printStackTrace(); + sys_exit(128+11); // SIGSEGV + exitException = e; + } catch(ExecutionException e) { + e.printStackTrace(); + System.err.println(e); + sys_exit(128+4); // SIGILL + exitException = e; + } + } + + /** Executes the process until the PAUSE syscall is invoked or the process exits. Returns true if the process exited. */ + public final boolean execute() { + if(state != PAUSED) throw new IllegalStateException("execute() called in inappropriate state"); + if(startTime == 0) startTime = System.currentTimeMillis(); + state = RUNNING; + __execute(); + if(state != PAUSED && state != DONE) throw new IllegalStateException("execute() ended up in an inappropriate state (" + state + ")"); + return state == DONE; + } + + public final int run() { return run(null); } + public final int run(String argv0, String[] rest) { + String[] args = new String[rest.length+1]; + System.arraycopy(rest,0,args,1,rest.length); + args[0] = argv0; + return run(args); + } + public final int run(String[] args) { return run(args,null); } + + /** Runs the process until it exits and returns the exit status. + If the process executes the PAUSE syscall execution will be paused for 500ms and a warning will be displayed */ + public final int run(String[] args, String[] env) { + start(args,env); + for(;;) { + if(execute()) break; + System.err.println("WARNING: Pause requested while executing run()"); + try { Thread.sleep(500); } catch(InterruptedException e) { /* noop */ } + } + return exitStatus(); + } + + public final void start() { start(null); } + public final void start(String[] args) { start(args,null); } + + /** Initializes the process and prepairs it to be executed with execute() */ + public final void start(String[] args, String[] environ) { + int sp, argsAddr, envAddr; + if(state != INITIALIZED) throw new IllegalStateException("start() called in inappropriate state"); + + if(args == null) args = new String[]{getClass().getName()}; + + sp = TOTAL_PAGES*PAGE_SIZE-512; + sp = argsAddr = addStringArray(args,sp); + sp = envAddr = addStringArray(createEnv(environ),sp); + sp &= ~15; + + CPUState cpuState = new CPUState(); + cpuState.r[A0] = argsAddr; + cpuState.r[A1] = envAddr; + cpuState.r[SP] = sp; + cpuState.r[RA] = 0xdeadbeef; + cpuState.r[GP] = gp; + cpuState.pc = entryPoint; + setCPUState(cpuState); + + state = PAUSED; + + _start(); + } + + /** Hook for subclasses to do their own startup */ + protected void _start() { /* noop */ } + + public final int call(String sym) throws CallException { return call(sym,0,0,0,0,0,0,0); } + public final int call(String sym, int a0) throws CallException { return call(sym,a0,0,0,0,0,0,0); } + public final int call(String sym, int a0, int a1) throws CallException { return call(sym,a0,a1,0,0,0,0,0); } + public final int call(String sym, int a0, int a1, int a2) throws CallException { return call(sym,a0,a1,a2,0,0,0,0); } + public final int call(String sym, int a0, int a1, int a2, int a3) throws CallException { return call(sym,a0,a1,a2,a3,0,0,0); } + public final int call(String sym, int a0, int a1, int a2, int a3, int a4) throws CallException { return call(sym,a0,a1,a2,a3,a4,0,0); } + public final int call(String sym, int a0, int a1, int a2, int a3, int a4, int a5) throws CallException { return call(sym,a0,a1,a2,a3,a4,a5,0); } + + /** Calls a function in the process with the given arguments */ + public final int call(String sym, int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws CallException { + int func = lookupSymbol(sym); + if(func == -1) throw new CallException(sym + " not found"); + int helper = lookupSymbol("_call_helper"); + if(helper == -1) throw new CallException("_call_helper not found"); + return call(helper,func,a0,a1,a2,a3,a4,a5,a6); + } + + /** Executes the code at addr in the process setting A0-A3 and S0-S3 to the given arguments + and returns the contents of V1 when the the pause syscall is invoked */ + public final int call(int addr, int a0, int a1, int a2, int a3, int s0, int s1, int s2, int s3) { + if(state != PAUSED && state != CALLJAVA) throw new IllegalStateException("call() called in inappropriate state"); + int oldState = state; + CPUState saved = getCPUState(); + CPUState cpustate = new CPUState(); + cpustate.r[SP] = saved.r[SP]&~15; + cpustate.r[RA] = 0xdeadbeef; + cpustate.r[A0] = a0; + cpustate.r[A1] = a1; + cpustate.r[A2] = a2; + cpustate.r[A3] = a3; + cpustate.r[S0] = s0; + cpustate.r[S1] = s1; + cpustate.r[S2] = s2; + cpustate.r[S3] = s3; + cpustate.r[GP] = gp; + cpustate.pc = addr; + + state = RUNNING; + + setCPUState(cpustate); + __execute(); + cpustate = getCPUState(); + setCPUState(saved); + + if(state != PAUSED) + System.out.println("WARNING: Process exit()ed while servicing a call() request"); + else + state = oldState; + + return cpustate.r[V1]; + } + + // FEATURE: This is ugly - we should have some kind of way to specify a callback rather than requiring subclassing + protected int callJava(int a, int b, int c, int d) { + System.err.println("WARNING: Default implementation of callJava() called with args " + toHex(a) + "," + toHex(b) + "," + toHex(c) + "," + toHex(d)); + return 0; + } + + /** Determines if the process can access fileName. The default implementation simply logs + the request and allows it */ + protected boolean allowFileAccess(String fileName, boolean write) { + //System.err.println("Allowing " + (write?"write":"read-only") + " access to " + fileName); + return true; + } + + /** Allocated an entry in the FileDescriptor table for fd and returns the number. + Returns -1 if the table is full. This can be used by subclasses to use custom file + descriptors */ + public int addFD(FD fd) { + int i; + for(i=0;ifdn and removes it from the file descriptor table */ + public boolean closeFD(int fdn) { + if(fdn < 0 || fdn >= OPEN_MAX) return false; + if(fds[fdn] == null) return false; + fds[fdn].close(); + fds[fdn] = null; + return true; + } + + // FEATURE: These should be pulled in from UsermodeConstants but fcntl.h is hard to parse + public static final int RD_ONLY = 0; + public static final int WR_ONLY = 1; + public static final int RDWR = 2; + + public static final int O_CREAT = 0x0200; + public static final int O_EXCL = 0x0800; + public static final int O_APPEND = 0x0008; + public static final int O_TRUNC = 0x0400; + public static final int O_NONBLOCK = 0x4000; + + // FEATURE: Lots of duplicate code between this and UnixRuntime.HostFS.open() + protected FD open(String path, int flags, int mode) throws IOException { + final File f = new File(path); + // NOTE: createNewFile is a Java2 function + if((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) + if(!f.createNewFile()) throw new ErrnoException(EEXIST); + if(!f.exists() && (flags&O_CREAT) == 0) return null; + if(f.isDirectory()) return null; + final SeekableFile sf = new SeekableFile(path,mode!=RD_ONLY); + if((flags&O_TRUNC)!=0) sf.setLength(0); + return new SeekableFD(sf,flags) { + protected FStat _fstat() { return new HostFStat(f) { + public int size() { + try { return sf.length(); } catch(IOException e) { return 0; } + } + };} + }; + } + + /** The open syscall */ + private int sys_open(int addr, int flags, int mode) { + if((flags & O_NONBLOCK) != 0) { + System.err.println("WARNING: O_NONBLOCK not supported"); + return -EOPNOTSUPP; + } + + try { + FD fd = open(cstring(addr),flags,mode); + if(fd == null) return -ENOENT; + int fdn = addFD(fd); + if(fdn == -1) { + fd.close(); + return -ENFILE; + } + return fdn; + } + catch(ErrnoException e) { return -e.errno; } + catch(FileNotFoundException e) { + if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) return -EACCES; + return -ENOENT; + } + catch(IOException e) { return -EIO; } + catch(FaultException e) { return -EFAULT; } + } + + /** The write syscall */ + private int sys_write(int fdn, int addr, int count) { + count = Math.min(count,MAX_CHUNK); + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null || !fds[fdn].writable()) return -EBADFD; + try { + byte[] buf = byteBuf(count); + copyin(addr,buf,count); + return fds[fdn].write(buf,0,count); + } catch(FaultException e) { + System.err.println(e); + return -EFAULT; + } catch(IOException e) { + // FEATURE: We should support signals and send a SIGPIPE + if(e.getMessage().equals("Pipe closed")) return sys_exit(128+13); + System.err.println(e); + return -EIO; + } + } + + /** The read syscall */ + private int sys_read(int fdn, int addr, int count) { + count = Math.min(count,MAX_CHUNK); + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null || !fds[fdn].readable()) return -EBADFD; + try { + byte[] buf = byteBuf(count); + int n = fds[fdn].read(buf,0,count); + copyout(buf,addr,n); + return n; + } catch(FaultException e) { + System.err.println(e); + return -EFAULT; + } catch(IOException e) { + System.err.println(e); + return -EIO; + } + } + + /** The close syscall */ + private int sys_close(int fdn) { + return closeFD(fdn) ? 0 : -EBADFD; + } + + + /** The seek syscall */ + private int sys_lseek(int fdn, int offset, int whence) { + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + if(whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) return -EINVAL; + try { + int n = fds[fdn].seek(offset,whence); + return n < 0 ? -ESPIPE : n; + } catch(IOException e) { + return -ESPIPE; + } + } + + /** The stat/fstat syscall helper */ + int stat(FStat fs, int addr) { + try { + memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16) + memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // st_mode + memWrite(addr+8,1<<16); // st_nlink (top 16) // st_uid (bottom 16) + memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16) + memWrite(addr+16,fs.size()); // st_size + memWrite(addr+20,fs.atime()); // st_atime + // memWrite(addr+24,0) // st_spare1 + memWrite(addr+28,fs.mtime()); // st_mtime + // memWrite(addr+32,0) // st_spare2 + memWrite(addr+36,fs.ctime()); // st_ctime + // memWrite(addr+40,0) // st_spare3 + memWrite(addr+44,fs.blksize()); // st_bklsize; + memWrite(addr+48,fs.blocks()); // st_blocks + // memWrite(addr+52,0) // st_spare4[0] + // memWrite(addr+56,0) // st_spare4[1] + } catch(FaultException e) { + System.err.println(e); + return -EFAULT; + } + return 0; + } + + /** The fstat syscall */ + private int sys_fstat(int fdn, int addr) { + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + return stat(fds[fdn].fstat(),addr); + } + + /* + struct timeval { + long tv_sec; + long tv_usec; + }; + */ + private int sys_gettimeofday(int timevalAddr, int timezoneAddr) { + long now = System.currentTimeMillis(); + int tv_sec = (int)(now / 1000); + int tv_usec = (int)((now%1000)*1000); + try { + memWrite(timevalAddr+0,tv_sec); + memWrite(timevalAddr+4,tv_usec); + return 0; + } catch(FaultException e) { + return -EFAULT; + } + } + + private int sys_sleep(int sec) { + if(sec < 0) sec = Integer.MAX_VALUE; + try { + Thread.sleep((long)sec*1000); + return 0; + } catch(InterruptedException e) { + return -1; + } + } + + /* + #define _CLOCKS_PER_SEC_ 1000 + #define _CLOCK_T_ unsigned long + struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; + };*/ + + private int sys_times(int tms) { + long now = System.currentTimeMillis(); + int userTime = (int)((now - startTime)/16); + int sysTime = (int)((now - startTime)/16); + + try { + if(tms!=0) { + memWrite(tms+0,userTime); + memWrite(tms+4,sysTime); + memWrite(tms+8,userTime); + memWrite(tms+12,sysTime); + } + } catch(FaultException e) { + return -EFAULT; + } + return (int)now; + } + + private int sys_sysconf(int n) { + switch(n) { + case _SC_CLK_TCK: return 1000; + default: + System.err.println("WARNING: Attempted to use unknown sysconf key: " + n); + return -EINVAL; + } + } + + /** The sbrk syscall. This can also be used by subclasses to allocate memory. + incr is how much to increase the break by */ + public int sbrk(int incr) { + if(incr < 0) return -ENOMEM; + if(incr==0) return brkAddr; + incr = (incr+3)&~3; + int oldBrk = brkAddr; + int newBrk = oldBrk + incr; + if(TOTAL_PAGES == 1) { + CPUState state = getCPUState(); + if(newBrk >= state.r[SP] - 65536) { + System.err.println("WARNING: brk too close to stack pointer"); + return -ENOMEM; + } + } else if(newBrk >= BRK_LIMIT) { + System.err.println("WARNING: Hit BRK_LIMIT"); + return -ENOMEM; + } + if(TOTAL_PAGES != 1) { + try { + for(int i=(oldBrk+PAGE_SIZE-1)>>>PAGE_SHIFT;i<((newBrk+PAGE_SIZE-1)>>>PAGE_SHIFT);i++) + readPages[i] = writePages[i] = emptyPage(); + } catch(OutOfMemoryError e) { + System.err.println("WARNING: Caught OOM Exception in sbrk: " + e); + return -ENOMEM; + } + } + brkAddr = newBrk; + return oldBrk; + } + + /** The getpid syscall */ + private int sys_getpid() { return getPid(); } + protected int getPid() { return 1; } + + private int sys_calljava(int a, int b, int c, int d) { + if(state != RUNNING) throw new IllegalStateException("wound up calling sys_calljava while not in RUNNING"); + state = CALLJAVA; + int ret = callJava(a,b,c,d); + state = RUNNING; + return ret; + } + + private int sys_pause() { + state = PAUSED; + return 0; + } + + private int sys_getpagesize() { return TOTAL_PAGES == 1 ? 4096 : PAGE_SIZE; } + + private int sys_isatty(int fdn) { + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + return fds[fdn].isatty() ? 1 : 0; + } + + + /** Hook for subclasses to do something when the process exits (MUST set state = DONE) */ + protected void _exit() { state = DONE; } + private int sys_exit(int status) { + exitStatus = status; + for(int i=0;i= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + FD fd = fds[fdn]; + + switch(cmd) { + case F_DUPFD: + if(arg < 0 || arg >= OPEN_MAX) return -EINVAL; + for(i=arg;isyscall should be the contents of V0 and a, b, c, and d should be + the contenst of A0, A1, A2, and A3. The call MAY change the state + @see Runtime#state state */ + protected int syscall(int syscall, int a, int b, int c, int d) { + switch(syscall) { + case SYS_null: return 0; + case SYS_exit: return sys_exit(a); + case SYS_pause: return sys_pause(); + case SYS_write: return sys_write(a,b,c); + case SYS_fstat: return sys_fstat(a,b); + case SYS_sbrk: return sbrk(a); + case SYS_open: return sys_open(a,b,c); + case SYS_close: return sys_close(a); + case SYS_read: return sys_read(a,b,c); + case SYS_lseek: return sys_lseek(a,b,c); + case SYS_getpid: return sys_getpid(); + case SYS_calljava: return sys_calljava(a,b,c,d); + case SYS_gettimeofday: return sys_gettimeofday(a,b); + case SYS_sleep: return sys_sleep(a); + case SYS_times: return sys_times(a); + case SYS_getpagesize: return sys_getpagesize(); + case SYS_isatty: return sys_isatty(a); + case SYS_fcntl: return sys_fcntl(a,b,c); + case SYS_sysconf: return sys_sysconf(a); + + case SYS_kill: + case SYS_fork: + case SYS_pipe: + case SYS_dup2: + case SYS_waitpid: + case SYS_stat: + case SYS_mkdir: + case SYS_getcwd: + case SYS_chdir: + System.err.println("Attempted to use a UnixRuntime syscall in Runtime (" + syscall + ")"); + return -ENOSYS; + default: + System.err.println("Attempted to use unknown syscall: " + syscall); + return -ENOSYS; + } + } + + public int xmalloc(int size) { int p=malloc(size); if(p==0) throw new RuntimeException("malloc() failed"); return p; } + public int xrealloc(int addr,int newsize) { int p=realloc(addr,newsize); if(p==0) throw new RuntimeException("realloc() failed"); return p; } + public int realloc(int addr, int newsize) { try { return call("realloc",addr,newsize); } catch(CallException e) { return 0; } } + public int malloc(int size) { try { return call("malloc",size); } catch(CallException e) { return 0; } } + public void free(int p) { try { if(p!=0) call("free",p); } catch(CallException e) { /*noop*/ } } + + /** Helper function to create a cstring in main memory */ + public int strdup(String s) { + byte[] a; + if(s == null) s = "(null)"; + byte[] a2 = getBytes(s); + a = new byte[a2.length+1]; + System.arraycopy(a2,0,a,0,a2.length); + int addr = malloc(a.length); + if(addr == 0) return 0; + try { + copyout(a,addr,a.length); + } catch(FaultException e) { + free(addr); + return 0; + } + return addr; + } + + /** Helper function to read a cstring from main memory */ + public String cstring(int addr) throws ReadFaultException { + StringBuffer sb = new StringBuffer(); + for(;;) { + int word = memRead(addr&~3); + switch(addr&3) { + case 0: if(((word>>>24)&0xff)==0) return sb.toString(); sb.append((char)((word>>>24)&0xff)); addr++; + case 1: if(((word>>>16)&0xff)==0) return sb.toString(); sb.append((char)((word>>>16)&0xff)); addr++; + case 2: if(((word>>> 8)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 8)&0xff)); addr++; + case 3: if(((word>>> 0)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 0)&0xff)); addr++; + } + } + } + + /** File Descriptor class */ + public static abstract class FD { + private int refCount = 1; + + /** returns true if the fd is readable */ + public boolean readable() { return false; } + /** returns true if the fd is writable */ + public boolean writable() { return false; } + + /** Read some bytes. Should return the number of bytes read, 0 on EOF, or throw an IOException on error */ + public int read(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } + /** Write. Should return the number of bytes written or throw an IOException on error */ + public int write(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } + + /** Seek in the filedescriptor. Whence is SEEK_SET, SEEK_CUR, or SEEK_END. Should return -1 on error or the new position. */ + public int seek(int n, int whence) throws IOException { return -1; } + + /** Should return true if this is a tty */ + public boolean isatty() { return false; } + + private FStat cachedFStat = null; + public final FStat fstat() { + if(cachedFStat == null) cachedFStat = _fstat(); + return cachedFStat; + } + + protected abstract FStat _fstat(); + + /** Closes the fd */ + public final void close() { if(--refCount==0) _close(); } + protected void _close() { /* noop*/ } + + FD dup() { refCount++; return this; } + } + + /** FileDescriptor class for normal files */ + public abstract static class SeekableFD extends FD { + private final int flags; + private final SeekableData data; + public boolean readable() { return (flags&3) != WR_ONLY; } + public boolean writable() { return (flags&3) != RD_ONLY; } + + SeekableFD(SeekableData data, int flags) { this.data = data; this.flags = flags; } + + protected abstract FStat _fstat(); + + public int seek(int n, int whence) throws IOException { + switch(whence) { + case SEEK_SET: break; + case SEEK_CUR: n += data.pos(); break; + case SEEK_END: n += data.length(); break; + default: return -1; + } + data.seek(n); + return n; + } + + public int write(byte[] a, int off, int length) throws IOException { + // NOTE: There is race condition here but we can't fix it in pure java + if((flags&O_APPEND) != 0) seek(0,SEEK_END); + return data.write(a,off,length); + } + + public int read(byte[] a, int off, int length) throws IOException { + int n = data.read(a,off,length); + return n < 0 ? 0 : n; + } + + protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } } + } + + public static class OutputStreamFD extends FD { + private OutputStream os; + public boolean writable() { return true; } + public OutputStreamFD(OutputStream os) { this.os = os; } + public int write(byte[] a, int off, int length) throws IOException { os.write(a,off,length); return length; } + public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ } } + public FStat _fstat() { return new FStat(); } + } + + public static class InputStreamFD extends FD { + private InputStream is; + public boolean readable() { return true; } + public InputStreamFD(InputStream is) { this.is = is; } + public int read(byte[] a, int off, int length) throws IOException { int n = is.read(a,off,length); return n < 0 ? 0 : n; } + public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } } + public FStat _fstat() { return new FStat(); } + } + + protected static class StdinFD extends InputStreamFD { + public StdinFD(InputStream is) { super(is); } + public void _close() { /* noop */ } + public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } + public boolean isatty() { return true; } + } + protected static class StdoutFD extends OutputStreamFD { + public StdoutFD(OutputStream os) { super(os); } + public void _close() { /* noop */ } + public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } + public boolean isatty() { return true; } + } + + public static class FStat { + public static final int S_IFIFO = 0010000; + public static final int S_IFCHR = 0020000; + public static final int S_IFDIR = 0040000; + public static final int S_IFREG = 0100000; + + public int dev() { return -1; } + // FEATURE: inode numbers are calculated inconsistently throught the runtime + public int inode() { return hashCode() & 0xfffff; } + public int mode() { return 0; } + public int type() { return S_IFIFO; } + public int nlink() { return 0; } + public int uid() { return 0; } + public int gid() { return 0; } + public int size() { return 0; } + public int atime() { return 0; } + public int mtime() { return 0; } + public int ctime() { return 0; } + public int blksize() { return 512; } + public int blocks() { return (size()+blksize()-1)/blksize(); } + } + + protected static class HostFStat extends FStat { + private final File f; + private final boolean executable; + public HostFStat(File f) { + this.f = f; + String name = f.getName(); + // FEATURE: This is ugly.. maybe we should do a file(1) type check + executable = name.endsWith(".mips") || name.endsWith(".sh"); + } + public int dev() { return 1; } + public int inode() { return f.getName().hashCode() & 0xffff; } + public int type() { return f.isDirectory() ? S_IFDIR : S_IFREG; } + public int nlink() { return 1; } + public int mode() { + int mode = 0; + boolean canread = f.canRead(); + if(canread && (executable || f.isDirectory())) mode |= 0111; + if(canread) mode |= 0444; + if(f.canWrite()) mode |= 0222; + return mode; + } + public int size() { return (int) f.length(); } + public int mtime() { return (int)(f.lastModified()/1000); } + } + + // Exceptions + public class ReadFaultException extends FaultException { + public ReadFaultException(int addr) { super(addr); } + } + public class WriteFaultException extends FaultException { + public WriteFaultException(int addr) { super(addr); } + } + public abstract class FaultException extends ExecutionException { + public int addr; + public FaultException(int addr) { super("fault at: " + toHex(addr)); this.addr = addr; } + } + public static class ExecutionException extends Exception { + private String message = "(null)"; + private String location = "(unknown)"; + public ExecutionException() { /* noop */ } + public ExecutionException(String s) { if(s != null) message = s; } + void setLocation(String s) { location = s == null ? "(unknown)" : s; } + public final String getMessage() { return message + " at " + location; } + } + public static class CallException extends Exception { + public CallException(String s) { super(s); } + } + + protected static class ErrnoException extends IOException { + public int errno; + public ErrnoException(int errno) { super("Errno: " + errno); this.errno = errno; } + } + + // CPU State + protected static class CPUState { + public CPUState() { /* noop */ } + /* GPRs */ + public int[] r = new int[32]; + /* Floating point regs */ + public int[] f = new int[32]; + public int hi, lo; + public int fcsr; + public int pc; + } + + // Null pointer check helper function + protected final void nullPointerCheck(int addr) throws ExecutionException { + if(TOTAL_PAGES==1 ? addr < 65536 : (addr>>>PAGE_SHIFT) < 16) + throw new ExecutionException("Attempted to dereference a null pointer " + toHex(addr)); + } + + // Utility functions + private byte[] byteBuf(int size) { + if(_byteBuf==null) _byteBuf = new byte[size]; + else if(_byteBuf.length < size) + _byteBuf = new byte[min(max(_byteBuf.length*2,size),MAX_CHUNK)]; + return _byteBuf; + } + + protected static String getSystemProperty(String key) { + try { + return System.getProperty(key); + } catch(SecurityException e) { + return null; + } + } + + /** Decode an packed string.. FEATURE: document this better */ + protected static final int[] decodeData(String s, int words) { + if(s.length() % 8 != 0) throw new IllegalArgumentException("string length must be a multiple of 8"); + if((s.length() / 8) * 7 < words*4) throw new IllegalArgumentException("string isn't big enough"); + int[] buf = new int[words]; + int prev = 0, left=0; + for(int i=0,n=0;n 0) buf[n++] = prev | (int)(l>>>(56-left)); + if(n < words) buf[n++] = (int) (l >>> (24-left)); + left = (left + 8) & 0x1f; + prev = (int)(l << left); + } + return buf; + } + + protected static byte[] getBytes(String s) { + try { + return s.getBytes("ISO-8859-1"); + } catch(UnsupportedEncodingException e) { + return null; // should never happen + } + } + + protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } + protected final static int min(int a, int b) { return a < b ? a : b; } + protected final static int max(int a, int b) { return a > b ? a : b; } +} diff --git a/src/org/xwt/mips/UnixRuntime.java b/src/org/xwt/mips/UnixRuntime.java new file mode 100644 index 0000000..8572ab9 --- /dev/null +++ b/src/org/xwt/mips/UnixRuntime.java @@ -0,0 +1,620 @@ +package org.xwt.mips; + +import org.xwt.mips.util.*; +import java.io.*; +import java.util.*; + +public abstract class UnixRuntime extends Runtime { + /** The pid of this "process" */ + private int pid; + private int ppid; + protected int getPid() { return pid; } + + /** processes filesystem */ + private FS fs; + public FS getFS() { return fs; } + public void setFS(FS fs) { + if(state >= RUNNING) throw new IllegalStateException("Can't change fs while process is running"); + this.fs = fs; + } + + /** proceses current working directory */ + private String cwd; + + /* Static stuff */ + // FEATURE: Most of this is O(n) or worse - fix it + private final Object waitNotification = new Object(); + private final static int MAX_TASKS = 256; + private final static UnixRuntime[] tasks = new UnixRuntime[MAX_TASKS]; + private static int addTask(UnixRuntime rt) { + synchronized(tasks) { + for(int i=1;i 0) sb.append("-"); + else off = -off; + sb.append(off/3600); off = off%3600; + if(off > 0) sb.append(":").append(off/60); off=off%60; + if(off > 0) sb.append(":").append(off); + if(zone.useDaylightTime()) + sb.append(zone.getDisplayName(true,TimeZone.SHORT)); + return sb.toString(); + } + + private static boolean envHas(String key,String[] environ) { + for(int i=0;i= 32) return -EINVAL; + switch(signal) { + case 0: return 0; + case 17: // SIGSTOP + case 18: // SIGTSTP + case 21: // SIGTTIN + case 22: // SIGTTOU + state = PAUSED; + break; + case 19: // SIGCONT + case 20: // SIGCHLD + case 23: // SIGIO + case 28: // SIGWINCH + break; + default: { + String msg = "Terminating on signal: " + signal + "\n"; + exitStatus = 1; + state = DONE; + if(fds[2]==null) { + System.out.print(msg); + } else { + try { + byte[] b = getBytes(msg); + fds[2].write(b,0,b.length); + } + catch(IOException e) { /* ignore */ } + } + } + } + return 0; + } + + private int sys_waitpid(int pid, int statusAddr, int options) { + final int WNOHANG = 1; + if((options & ~(WNOHANG)) != 0) return -EINVAL; + if(pid !=-1 && (pid <= 0 || pid >= MAX_TASKS)) return -ECHILD; + for(;;) { + synchronized(tasks) { + UnixRuntime task = null; + if(pid == -1) { + for(int i=0;i= sp-PAGE_SIZE*2) + System.arraycopy(writePages[i],0,r.writePages[i],0,PAGE_WORDS); + } else { + r.readPages[i] = r.readPages[i]; + } + } + state.r[V0] = 0; + state.pc += 4; + r.setCPUState(state); + r.state = PAUSED; + + new Thread() { + public void run() { + try { + while(!r.execute()); + } catch(Exception e) { + System.err.println("Forked process threw exception: "); + e.printStackTrace(); + } + } + }.start(); + + return child_pid; + } + + private int sys_pipe(int addr) { + PipedOutputStream writerStream = new PipedOutputStream(); + PipedInputStream readerStream; + try { + readerStream = new PipedInputStream(writerStream); + } catch(IOException e) { + return -EIO; + } + FD reader = new InputStreamFD(readerStream); + FD writer = new OutputStreamFD(writerStream); + int fd1 = addFD(reader); + if(fd1 < 0) return -ENFILE; + int fd2 = addFD(writer); + if(fd2 < 0) { closeFD(fd1); return -ENFILE; } + try { + memWrite(addr,fd1); + memWrite(addr+4,fd2); + } catch(FaultException e) { + closeFD(fd1); + closeFD(fd2); + return -EFAULT; + } + return 0; + } + + private int sys_dup2(int oldd, int newd) { + if(oldd == newd) return 0; + if(oldd < 0 || oldd >= OPEN_MAX) return -EBADFD; + if(newd < 0 || newd >= OPEN_MAX) return -EBADFD; + if(fds[oldd] == null) return -EBADFD; + if(fds[newd] != null) fds[newd].close(); + fds[newd] = fds[oldd].dup(); + return 0; + } + + private int sys_stat(int cstring, int addr) { + try { + String path = cleanupPath(cstring(cstring)); + return stat(fs.stat(path),addr); + } + catch(ErrnoException e) { return -e.errno; } + catch(FileNotFoundException e) { + if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) return -EACCES; + return -ENOENT; + } + catch(IOException e) { return -EIO; } + catch(FaultException e) { return -EFAULT; } + } + + + private int sys_mkdir(int cstring, int mode) { + try { + fs.mkdir(cleanupPath(cstring(cstring))); + return 0; + } + catch(ErrnoException e) { return -e.errno; } + catch(FileNotFoundException e) { return -ENOENT; } + catch(IOException e) { return -EIO; } + catch(FaultException e) { return -EFAULT; } + } + + + private int sys_getcwd(int addr, int size) { + byte[] b = getBytes(cwd); + if(size == 0) return -EINVAL; + if(size < b.length+1) return -ERANGE; + if(!new File(cwd).exists()) return -ENOENT; + try { + copyout(b,addr,b.length); + memset(addr+b.length+1,0,1); + return addr; + } catch(FaultException e) { + return -EFAULT; + } + } + + private int sys_chdir(int addr) { + try { + String path = cleanupPath(cstring(addr)); + System.err.println("Chdir: " + cstring(addr) + " -> " + path + " pwd: " + cwd); + if(fs.stat(path).type() != FStat.S_IFDIR) return -ENOTDIR; + cwd = path; + System.err.println("Now: " + cwd); + return 0; + } + catch(ErrnoException e) { return -e.errno; } + catch(FileNotFoundException e) { return -ENOENT; } + catch(IOException e) { return -EIO; } + catch(FaultException e) { return -EFAULT; } + } + + public void chdir(String dir) throws FileNotFoundException { + if(state >= RUNNING) throw new IllegalStateException("Can't chdir while process is running"); + try { + dir = cleanupPath(dir); + if(fs.stat(dir).type() != FStat.S_IFDIR) throw new FileNotFoundException(); + } catch(IOException e) { + throw new FileNotFoundException(); + } + cwd = dir; + } + + public abstract static class FS { + public FD open(String path, int flags, int mode) throws IOException { throw new FileNotFoundException(); } + public FStat stat(String path) throws IOException { throw new FileNotFoundException(); } + public void mkdir(String path) throws IOException { throw new ErrnoException(ENOTDIR); } + + public static FD directoryFD(String[] files, int hashCode) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + for(int i=0;i 0 && out[outp] != '/'); + } else if(in[inp+1] == '/') { + inp++; + } else { + out[outp++] = '/'; + } + } else { + out[outp++] = '/'; + out[outp++] = in[inp++]; + } + } else { + out[outp++] = in[inp++]; + } + } + if(outp == 0) out[outp++] = '/'; + return new String(out,0,outp); + } else { + if(p.startsWith("/")) return p; + StringBuffer sb = new StringBuffer(cwd); + if(!cwd.equals("/")) sb.append('/'); + return sb.append(p).toString(); + } + } + + // FEATURE: Probably should make this more general - support mountpoints, etc + public class UnixOverlayFS extends FS { + private final FS root; + private final FS dev = new DevFS(); + public UnixOverlayFS(FS root) { + this.root = root; + } + private String devPath(String path) { + if(path.startsWith("/dev")) { + if(path.length() == 4) return "/"; + if(path.charAt(4) == '/') return path.substring(4); + } + return null; + } + public FD open(String path, int flags, int mode) throws IOException{ + String dp = devPath(path); + return dp == null ? root.open(path,flags,mode) : dev.open(dp,flags,mode); + } + public FStat stat(String path) throws IOException { + String dp = devPath(path); + return dp == null ? root.stat(path) : dev.stat(dp); + } + public void mkdir(String path) throws IOException { + String dp = devPath(path); + if(dp == null) root.mkdir(path); + else dev.mkdir(dp); + } + } + + // FIXME: This is totally broken on non-unix hosts - need to do some kind of cygwin type mapping + public static class HostFS extends FS { + public static String fixPath(String path) throws FileNotFoundException { + return path; + } + + public String hostCWD() { + return getSystemProperty("user.dir"); + } + + // FEATURE: This shares a lot with Runtime.open + public FD open(String path, int flags, int mode) throws IOException { + path = fixPath(path); + final File f = new File(path); + // NOTE: createNewFile is a Java2 function + if((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) + if(!f.createNewFile()) throw new ErrnoException(EEXIST); + if(!f.exists() && (flags&O_CREAT) == 0) return null; + if(f.isDirectory()) { + if((flags&3)!=RD_ONLY) throw new ErrnoException(EACCES); + return directoryFD(f.list(),path.hashCode()); + } + final SeekableFile sf = new SeekableFile(path,(flags&3)!=RD_ONLY); + if((flags&O_TRUNC)!=0) sf.setLength(0); + return new SeekableFD(sf,mode) { + protected FStat _fstat() { return new HostFStat(f) { + public int size() { + try { return sf.length(); } catch(IOException e) { return 0; } + } + };} + }; + } + + public FStat stat(String path) throws FileNotFoundException { + File f = new File(fixPath(path)); + if(!f.exists()) throw new FileNotFoundException(); + return new HostFStat(f); + } + + public void mkdir(String path) throws IOException { + File f = new File(fixPath(path)); + if(f.exists() && f.isDirectory()) throw new ErrnoException(EEXIST); + if(f.exists()) throw new ErrnoException(ENOTDIR); + File parent = f.getParentFile(); + if(parent!=null && (!parent.exists() || !parent.isDirectory())) throw new ErrnoException(ENOTDIR); + if(!f.mkdir()) throw new ErrnoException(EIO); + } + } + + private static class DevFStat extends FStat { + public int dev() { return 1; } + public int mode() { return 0666; } + public int type() { return S_IFCHR; } + public int nlink() { return 1; } + } + private static FD devZeroFD = new FD() { + public boolean readable() { return true; } + public boolean writable() { return true; } + public int read(byte[] a, int off, int length) { Arrays.fill(a,off,off+length,(byte)0); return length; } + public int write(byte[] a, int off, int length) { return length; } + public int seek(int n, int whence) { return 0; } + public FStat _fstat() { return new DevFStat(); } + }; + private static FD devNullFD = new FD() { + public boolean readable() { return true; } + public boolean writable() { return true; } + public int read(byte[] a, int off, int length) { return 0; } + public int write(byte[] a, int off, int length) { return length; } + public int seek(int n, int whence) { return 0; } + public FStat _fstat() { return new DevFStat(); } + }; + + public class DevFS extends FS { + public FD open(String path, int mode, int flags) throws IOException { + if(path.equals("/null")) return devNullFD; + if(path.equals("/zero")) return devZeroFD; + if(path.startsWith("/fd/")) { + int n; + try { + n = Integer.parseInt(path.substring(4)); + } catch(NumberFormatException e) { + throw new FileNotFoundException(); + } + if(n < 0 || n >= OPEN_MAX) throw new FileNotFoundException(); + if(fds[n] == null) throw new FileNotFoundException(); + return fds[n].dup(); + } + if(path.equals("/fd")) { + int count=0; + for(int i=0;i= OPEN_MAX) throw new FileNotFoundException(); + if(fds[n] == null) throw new FileNotFoundException(); + return fds[n].fstat(); + } + if(path.equals("/fd")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }}; + if(path.equals("/")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }}; + throw new FileNotFoundException(); + } + + public void mkdir(String path) throws IOException { throw new ErrnoException(EACCES); } + } +} diff --git a/src/org/xwt/mips/crt0.c b/src/org/xwt/mips/crt0.c new file mode 100644 index 0000000..a85cdbc --- /dev/null +++ b/src/org/xwt/mips/crt0.c @@ -0,0 +1,31 @@ +#include + +extern int _gp[]; + +extern int main(int argc, char **argv, char **envp); +extern void exit(int status); +extern int atexit(void (*f)()); + +/* For constuctors/destructors */ +extern void _init(); +extern void _fini(); + +char **environ; + +void _start(char **argv, char **environ_) { + int argc; + + environ = environ_; + + /* Call global constructors */ + _init(); + + /* Register _fini() to be called on exit */ + atexit(_fini); + + /* Count the arguments */ + for(argc=0;argv[argc];argc++); + + /* Call main and exit */ + exit(main(argc,argv,environ)); +} diff --git a/src/org/xwt/mips/linker.ld b/src/org/xwt/mips/linker.ld new file mode 100644 index 0000000..c12be88 --- /dev/null +++ b/src/org/xwt/mips/linker.ld @@ -0,0 +1,60 @@ +ENTRY(_start) +INPUT(support.o support_aux.o) +GROUP(-lc -lgcc) +/*GROUP(-lgcc)*/ +__DYNAMIC = 0; + +SECTIONS { + . = 0x10000; + .text : { + KEEP(*(.init)) + KEEP(*(.fini)) + KEEP(*(.text)) + *(.text.*) + *(.gnu.linkonce.t*) + } + + _etext = .; + + .ctors : + { + KEEP (*crtbegin.o(.ctors)) + 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)) + } + + . = ALIGN(4k); + + .rodata : { + *(.rodata*) *(.gnu.linkonce.r*) + *(.gcc_except_table) + KEEP(*(.eh_frame)) KEEP(*(.jcr)) + } + + .data : { + *(.data*) *(.gnu.linkonce.d*) + } + + . = ALIGN(16); + _gp = . + 0x8000; + .sdata : { + *(.rosdata*) *(.sdata*) *(.gnu.linkonce.s*) + } + .sbss : { + *(.sbss*) *(.scommon*) + } + .bss : { + *(.bss*) *(.gnu.linkonce.b*) *(COMMON) + } + + _end = .; +} diff --git a/src/org/xwt/mips/support.s b/src/org/xwt/mips/support.s new file mode 100644 index 0000000..b7781d5 --- /dev/null +++ b/src/org/xwt/mips/support.s @@ -0,0 +1,122 @@ +#include "syscalls.h" + +#define zero $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 ra $31 + +/* We intentionally don't take advantage of delay slots because + the compiler removes them anyway */ + +.set noreorder; + +#define SYSCALL(name) SYSCALL2(name,SYS_##name) +#define SYSCALL2(name,number) \ + .section .text.name,"ax",@progbits; \ + .align 2; \ + .globl name; \ + .ent name; \ +name: \ + li v0, number; \ + syscall; \ + j ra; \ + nop; \ + .end name; + +#define SYSCALL_R(name) \ + .section .text._##name##_r,"ax",@progbits; \ + .align 2; \ + .globl _##name##_r; \ + .ent _##name##_r; \ +_##name##_r: \ + li v0, SYS_##name; \ + move t0, a0; \ + move a0, a1; \ + move a1, a2; \ + move a2, a3; \ + syscall; \ + addu t1,v0,255; \ + sltu t1,t1,255; \ + bne t1,zero,$L##name##_errno;\ + nop; \ + j ra; \ + nop; \ +$L##name##_errno: \ + move a0, t0; \ + move a1, v0; \ + j _syscall_set_errno; \ + nop; \ + .end _##name##_r; + + + .align 2 + .globl _call_helper + .ent _call_helper +_call_helper: + subu $sp,$sp,32 + + /* addr */ + move $2,$4 + + /* args 1-4 */ + move $4,$5 + move $5,$6 + move $6,$7 + move $7,$16 + + /* args 5 and 6 */ + sw $17,16($sp) + sw $18,20($sp) + + /* call the func */ + jal $31,$2 + nop + + move $3,$2 + li $2,SYS_pause + syscall + + /* shouldn't get here */ + li $2,SYS_exit + li $3,1 + syscall + + .end _call_helper + +SYSCALL2(_exit,SYS_exit) +SYSCALL2(_pause,SYS_pause) +SYSCALL_R(open) +SYSCALL_R(close) +SYSCALL_R(read) +SYSCALL_R(write) +SYSCALL_R(sbrk) +SYSCALL_R(fstat) +SYSCALL(isatty) +SYSCALL_R(lseek) +SYSCALL_R(kill) +SYSCALL_R(getpid) +SYSCALL2(_call_java,SYS_calljava) +SYSCALL_R(stat) +SYSCALL_R(gettimeofday) +SYSCALL(sleep) +SYSCALL_R(times) +SYSCALL_R(mkdir) +SYSCALL(getpagesize) +SYSCALL_R(unlink) +SYSCALL_R(utime) +SYSCALL_R(chdir) +SYSCALL_R(pipe) +SYSCALL_R(dup2) +SYSCALL_R(fork) +SYSCALL_R(waitpid) +SYSCALL_R(getcwd) +SYSCALL_R(execve) +SYSCALL_R(fcntl) +SYSCALL_R(rmdir) +SYSCALL_R(sysconf) diff --git a/src/org/xwt/mips/support_aux.c b/src/org/xwt/mips/support_aux.c new file mode 100644 index 0000000..9800e4a --- /dev/null +++ b/src/org/xwt/mips/support_aux.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int _syscall_set_errno(struct _reent *ptr, int err) { + ptr->_errno = -err; + return -1; +} + +extern int _stat_r(struct _reent *ptr, const char *path, struct stat *sb); +int _lstat_r(struct _reent *ptr, const char *path, struct stat *sb) { + return _stat_r(ptr,path,sb); +} + +uid_t getuid() { return 0; } +gid_t getgid() { return 0; } +uid_t geteuid() { return 0; } +gid_t getegid() { return 0; } +int getgroups(int gidsetlen, gid_t *gidset) { + if(gidsetlen) *gidset = 0; + return 1; +} +mode_t umask(mode_t new) { return 0022; } + +static int syscall_nosys(struct _reent *ptr) { + ptr->_errno = ENOSYS; + return -1; +} + +int _access_r(struct _reent *ptr, const char *pathname, int mode) { + struct stat statbuf; + if(_stat_r(ptr,pathname,&statbuf) < 0) return -1; + return 0; +} + +/* FIXME: These should be in newlib */ +int access(const char *pathname, int mode) { return _access_r(_REENT,pathname,mode); } +extern int _rmdir_r(struct _reent *ptr, const char *pathname); +int rmdir(const char *pathname) { return _rmdir_r(_REENT,pathname); } +extern long _sysconf_r(struct _reent *ptr, int n); +long sysconf(int n) { return _sysconf_r(_REENT,n); } + +#define SYSCALL_NOSYS_R(name) int _##name##_r(struct _reent *ptr) { return syscall_nosys(ptr); } + +SYSCALL_NOSYS_R(link) +SYSCALL_NOSYS_R(symlink) +SYSCALL_NOSYS_R(readlink) +SYSCALL_NOSYS_R(chown) +SYSCALL_NOSYS_R(fchown) +SYSCALL_NOSYS_R(chmod) +SYSCALL_NOSYS_R(fchmod) + +static int read_fully(int fd, void *buf, size_t size) { + int n; + while(size) { + n = read(fd,buf,size); + if(n <= 0) return -1; + size -= n; + buf += n; + } + return 0; +} + +DIR *opendir(const char *path) { + struct stat sb; + int fd; + DIR *dir; + + fd = open(path,O_RDONLY); + if(fd < 0) return NULL; + + if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) { + close(fd); + errno = ENOTDIR; + return NULL; + } + + dir = malloc(sizeof(*dir)); + if(dir == NULL) { + close(fd); + errno = ENOMEM; + return NULL; + } + dir->dd_fd = fd; + dir->dd_pos = 0; + return dir; +} + +static int readdir_r(DIR *dir,struct dirent *entry, struct dirent **result) { + struct { + int inode; + int name_len; + } h; + if(dir->dd_fd < 0) return -1; +again: + if(read_fully(dir->dd_fd,&h,sizeof(h)) < 0) goto fail; + if(h.name_len < 0 || h.name_len >= sizeof(entry->d_name)-1) goto fail; + + entry->d_ino = h.inode; + if(read_fully(dir->dd_fd,entry->d_name,h.name_len) < 0) goto fail; + + entry->d_name[h.name_len] = '\0'; + dir->dd_pos += h.name_len + 8; + + if(result) *result = entry; + return 0; +fail: + if(result) *result = NULL; + return -1; +} + +struct dirent *readdir(DIR *dir) { return readdir_r(dir,&dir->ent,NULL) == 0 ? &dir->ent : NULL; } + +int closedir(DIR *dir) { + close(dir->dd_fd); + free(dir); + return 0; +} diff --git a/src/org/xwt/mips/syscalls.h b/src/org/xwt/mips/syscalls.h new file mode 100644 index 0000000..5a1edf3 --- /dev/null +++ b/src/org/xwt/mips/syscalls.h @@ -0,0 +1,32 @@ +#define SYS_null 0 +#define SYS_exit 1 +#define SYS_pause 2 +#define SYS_open 3 +#define SYS_close 4 +#define SYS_read 5 +#define SYS_write 6 +#define SYS_sbrk 7 +#define SYS_fstat 8 +#define SYS_isatty 9 +#define SYS_lseek 10 +#define SYS_kill 11 +#define SYS_getpid 12 +#define SYS_calljava 13 +#define SYS_stat 14 +#define SYS_gettimeofday 15 +#define SYS_sleep 16 +#define SYS_times 17 +#define SYS_mkdir 18 +#define SYS_getpagesize 19 +#define SYS_unlink 20 +#define SYS_utime 21 +#define SYS_chdir 22 +#define SYS_pipe 23 +#define SYS_dup2 24 +#define SYS_fork 25 +#define SYS_waitpid 26 +#define SYS_getcwd 27 +#define SYS_execve 28 +#define SYS_fcntl 29 +#define SYS_rmdir 30 +#define SYS_sysconf 31 diff --git a/src/org/xwt/mips/util/SeekableByteArray.java b/src/org/xwt/mips/util/SeekableByteArray.java new file mode 100644 index 0000000..807dd68 --- /dev/null +++ b/src/org/xwt/mips/util/SeekableByteArray.java @@ -0,0 +1,37 @@ +package org.xwt.mips.util; + +import java.io.IOException; + +public class SeekableByteArray implements SeekableData { + protected byte[] data; + protected int pos; + private final boolean writable; + + public SeekableByteArray(byte[] data, boolean writable) { + this.data = data; + this.pos = 0; + this.writable = writable; + } + + public int read(byte[] buf, int off, int len) { + len = Math.min(len,data.length-pos); + if(len <= 0) return -1; + System.arraycopy(data,pos,buf,off,len); + pos += len; + return len; + } + + public int write(byte[] buf, int off, int len) throws IOException { + if(!writable) throw new IOException("read-only data"); + len = Math.min(len,data.length-pos); + if(len <= 0) throw new IOException("no space"); + System.arraycopy(buf,off,data,pos,len); + pos += len; + return len; + } + + public int length() { return data.length; } + public int pos() { return pos; } + public void seek(int pos) { this.pos = pos; } + public void close() { /*noop*/ } +} diff --git a/src/org/xwt/mips/util/SeekableData.java b/src/org/xwt/mips/util/SeekableData.java new file mode 100644 index 0000000..2603aba --- /dev/null +++ b/src/org/xwt/mips/util/SeekableData.java @@ -0,0 +1,12 @@ +package org.xwt.mips.util; + +import java.io.IOException; + +public interface SeekableData { + public int read(byte[] buf, int offset, int length) throws IOException; + public int write(byte[] buf, int offset, int length) throws IOException; + public int length() throws IOException; + public void seek(int pos) throws IOException; + public void close() throws IOException; + public int pos() throws IOException; +} diff --git a/src/org/xwt/mips/util/SeekableFile.java b/src/org/xwt/mips/util/SeekableFile.java new file mode 100644 index 0000000..168d43a --- /dev/null +++ b/src/org/xwt/mips/util/SeekableFile.java @@ -0,0 +1,24 @@ +package org.xwt.mips.util; + +import java.io.*; + +public class SeekableFile implements SeekableData { + private final RandomAccessFile raf; + + public SeekableFile(String fileName) throws IOException { this(fileName,false); } + public SeekableFile(String fileName, boolean writable) throws IOException { this(new File(fileName),writable); } + + public SeekableFile(File file, boolean writable) throws IOException { + raf = new RandomAccessFile(file,writable ? "rw" : "r"); + } + + // NOTE: RandomAccessFile.setLength() is a Java2 function + public void setLength(int n) throws IOException { raf.setLength(n); } + + public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); } + public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; } + public void seek(int pos) throws IOException{ raf.seek(pos); } + public int pos() throws IOException { return (int) raf.getFilePointer(); } + public int length() throws IOException { return (int)raf.length(); } + public void close() throws IOException { raf.close(); } +} diff --git a/src/org/xwt/mips/util/SeekableInputStream.java b/src/org/xwt/mips/util/SeekableInputStream.java new file mode 100644 index 0000000..1dc0b0d --- /dev/null +++ b/src/org/xwt/mips/util/SeekableInputStream.java @@ -0,0 +1,48 @@ +package org.xwt.mips.util; + +import java.io.*; + +public class SeekableInputStream implements SeekableData { + private byte[] buffer = new byte[4096]; + private int bytesRead = 0; + private boolean eof = false; + private int pos; + private InputStream is; + + public SeekableInputStream(InputStream is) { this.is = is; } + + public int read(byte[] outbuf, int off, int len) throws IOException { + if(pos >= bytesRead && !eof) readTo(pos + 1); + len = Math.min(len,bytesRead-pos); + if(len <= 0) return -1; + System.arraycopy(buffer,pos,outbuf,off,len); + pos += len; + return len; + } + + private void readTo(int target) throws IOException { + if(target >= buffer.length) { + byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)]; + System.arraycopy(buffer,0,buf2,0,bytesRead); + buffer = buf2; + } + while(bytesRead < target) { + int n = is.read(buffer,bytesRead,buffer.length-bytesRead); + if(n == -1) { + eof = true; + break; + } + bytesRead += n; + } + } + + public int length() throws IOException { + while(!eof) readTo(bytesRead+4096); + return bytesRead; + } + + public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); } + public void seek(int pos) { this.pos = pos; } + public int pos() { return pos; } + public void close() throws IOException { is.close(); } +} diff --git a/src/tests/CXXTest.cc b/src/tests/CXXTest.cc new file mode 100644 index 0000000..21b3972 --- /dev/null +++ b/src/tests/CXXTest.cc @@ -0,0 +1,54 @@ +#include + +using namespace std; + +class Test { +public: + Test(); + ~Test(); + void sayhi(); +}; + +class Exn { +public: + Exn() { } +}; + + +Test test; + +int main(int argc,char *argv[]) { + printf("Name: %p\n",typeid(const char*).name()); + printf("Name: %s\n",typeid(const char*).name()); + printf("Is pointer: %d\n",typeid(const char*).__is_pointer_p ()); + printf("Name: %p\n",typeid(int).name()); + printf("Name: %s\n",typeid(int).name()); + printf("Is pointer: %d\n",typeid(int).__is_pointer_p ()); + + try { + test.sayhi(); + } catch(char *e) { + printf("sayhi threw: %s\n",e); + } catch(const char *e) { + printf("sayhi threw: const char *:%s\n",e); + } catch(int n) { + printf("sayhi threw: %d\n",n); + } + return 0; +} + +Test::Test() { + cout << "Test's constructor" << endl; +} + +Test::~Test() { + cout << "Test's destructor" << endl; +} + +void Test::sayhi() { + static char exn[] = "Non-const!"; + cout << "Hello, World from Test" << endl; + cout << "Now throwing an exception" << endl; + throw "Hello, Exception Handling!"; + //throw exn; +} diff --git a/src/tests/CallTest.java b/src/tests/CallTest.java new file mode 100644 index 0000000..0e56a5f --- /dev/null +++ b/src/tests/CallTest.java @@ -0,0 +1,66 @@ +package tests; + +import org.xwt.mips.Runtime; +import org.xwt.mips.Interpreter; +import java.io.*; +import java.util.*; + +public class CallTest { + public static void main(String[] args) throws Exception { + int a1 = args.length > 0 ? Integer.parseInt(args[0]) : 0; + int a2 = args.length > 1 ? Integer.parseInt(args[1]) : 0; + int a3 = args.length > 2 ? Integer.parseInt(args[2]) : 0; + int a4 = args.length > 3 ? Integer.parseInt(args[3]) : 0; + int a5 = args.length > 4 ? Integer.parseInt(args[4]) : 0; + int a6 = args.length > 5 ? Integer.parseInt(args[5]) : 0; + + System.out.println("Version is: " + System.getProperty("os.version")); + Runtime rt; + if(a1 == 99) // yeah.. this is ugly + rt = new Interpreter("build/tests/Test.mips"); + else + rt = new Test() { + protected int callJava(int a, int b, int c, int d) { + switch(a) { + case 1: return strdup("OS: " + System.getProperty("os.name")); + case 2: return strdup(System.getProperty("os.version")); + case 3: return strdup(new Date().toString()); + case 4: return allocFDEnt(new OutputStreamFD(new CustomOS())); + case 5: + System.out.println("In callJava() in Java"); + try { call("backinmips"); } catch(CallException e) { } + System.out.println("Back in callJava() in Java"); + return 0; + default: return super.callJava(a,b,c,d); + } + } + }; + System.out.println("Runtime: " + rt); + + rt.start(new String[]{"Test","calltest"}); + rt.execute(); + + System.out.println("== Start of CallTest =="); + System.out.println("Back in java... calling callme()"); + int ret = rt.call("callme",a1,a2,a3,a4,a5,a6); + System.out.println("callme returned: " + ret); + + int addr = rt.strdup("Hello, World from java"); + rt.call("echo",addr,4); + rt.free(addr); + System.out.println("== End of CallTest =="); + + rt.execute(); + System.exit(rt.exitStatus()); + } + + private static class CustomOS extends OutputStream { + public CustomOS() { } + public void write(int b) { byte[] a = new byte[1]; a[0] = (byte)(b&0xff); write(a,0,1); } + public void write(byte[] b, int off, int len) { + int len2 = len; + while(b[len2-1]=='\n') len2--; + System.out.println("This just in from MIPS: " + new String(b,off,len2)); + } + } +} diff --git a/src/tests/Echo.java b/src/tests/Echo.java new file mode 100644 index 0000000..47f8046 --- /dev/null +++ b/src/tests/Echo.java @@ -0,0 +1,35 @@ +package tests; + +import java.net.*; + +import org.xwt.mips.Runtime; + +public class Echo { + private static final int PORT = 2000; + public static void main(String[] args) throws Exception { + ServerSocket sock = new ServerSocket(PORT); + System.err.println("Listening on " + PORT); + for(;;) new Client(sock.accept()).go(); + } + + private static class Client implements Runnable { + private Socket sock; + public Client(Socket sock) { this.sock = sock; } + public void go() { new Thread(this).start(); } + public void run() { + try { + Runtime task = new EchoHelper(); + int status = task.run( + new String[]{"EchoHelper"}, + null, + new Runtime.InputStreamFD(sock.getInputStream()), + new Runtime.OutputStreamFD(sock.getOutputStream()), + null + ); + System.err.println("Exit status: " + status); + } catch(Exception e) { + System.err.println(e); + } + } + } +} diff --git a/src/tests/EchoHelper.c b/src/tests/EchoHelper.c new file mode 100644 index 0000000..f1cf1a4 --- /dev/null +++ b/src/tests/EchoHelper.c @@ -0,0 +1,16 @@ +#include +#include + +int main() { + char buf[1024]; + char *p; + printf("Hello! Welcome to EchoHelper.c\n"); + while(fgets(buf,sizeof(buf),stdin) != NULL) { + for(p=buf;*p && *p!='\n' && *p!='\r';p++); + *p = '\0'; + fprintf(stdout,"You said: %s\n",buf); + fprintf(stderr,"They said: %s\n",buf); + if(strcmp(buf,"exit")==0) break; + } + return 0; +} diff --git a/src/tests/Env.java b/src/tests/Env.java new file mode 100644 index 0000000..59048b5 --- /dev/null +++ b/src/tests/Env.java @@ -0,0 +1,32 @@ +package tests; + +import org.xwt.mips.Runtime; +import org.xwt.mips.Interpreter; + +class Env { + public static void main(String[] args) throws Exception { + int n = 0; + while(n < args.length && args[n].indexOf("=") != -1) n++; + + if(n==args.length) { + System.err.println("Usage: Env [name=value ...] classname [args ...]"); + System.exit(1); + } + + String[] env = new String[n]; + String[] appArgs = new String[args.length-n-1]; + for(int i=0;i +#include +#include +#include + +#define FT_Check(expr) do { \ + if((expr) != 0) { \ + fprintf(stderr,#expr " failed\n"); \ + exit(EXIT_FAILURE); \ + } \ +} while(0) + +#define BMP_WIDTH 800 +#define BMP_HEIGHT 600 + +static char buf[BMP_WIDTH*BMP_HEIGHT]; + +int main(int argc, char **argv) { + char *ttf; + char *out; + FT_Library library; + FT_Face face; + FT_GlyphSlot glyph; + int num_glyphs; + int c; + int glyph_index; + int loc_x; + int loc_y; + int glyph_width; + int glyph_height; + int i,j; + int fd; + char *p; + int n,count; + char *glyph_buf; + int pixel_size; + + if(argc < 3) { + fprintf(stderr,"Usage: %s ttf bmp\n",argv[0]); + exit(1); + } + + ttf = argv[1]; + out = argv[2]; + + memset(buf,'\377',BMP_WIDTH*BMP_HEIGHT); + + FT_Check(FT_Init_FreeType(&library)); + FT_Check(FT_New_Face(library,ttf,0,&face)); + + loc_y = loc_x = 0; + for(pixel_size=8;pixel_size<48;pixel_size+=4) { + FT_Check(FT_Set_Pixel_Sizes(face,0,pixel_size)); + for(c=32;c<127;c++) { + glyph_index = FT_Get_Char_Index(face,c); + FT_Check(FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT)); + FT_Check(FT_Render_Glyph(face->glyph, ft_render_mode_normal)); + glyph = face->glyph; + glyph_width = glyph->bitmap.width; + glyph_height = glyph->bitmap.rows; + glyph_buf = glyph->bitmap.buffer; + if(loc_x + glyph_width + glyph->bitmap_left >= BMP_WIDTH) { + loc_x = 0; + loc_y += pixel_size; + if(loc_y >= BMP_HEIGHT-pixel_size) goto done; + } + + for(i=0;iglyph->advance.x/64; + } + } +done: + + if((fd = open(out,O_CREAT|O_WRONLY,0644)) < 0) { + perror("open"); + exit(1); + } + p = buf; + count = BMP_WIDTH*BMP_HEIGHT; + + while(count) { + n = write(fd,p,count); + if(n < 0) { + perror("write"); + exit(1); + } + count -=n; + p += n; + } + close(fd); + + return 0; +} diff --git a/src/tests/Fork.c b/src/tests/Fork.c new file mode 100644 index 0000000..088ebaf --- /dev/null +++ b/src/tests/Fork.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +int main() { + fprintf(stderr,"In the main process (pid: %d), about to fork\n",getpid()); + pid_t pid = fork(); + int status; + int i; + + switch(pid) { + case -1: perror("fork"); break; + case 0: + fprintf(stderr,"In the forked process (pid: %d), sleeping for 2 sec\n",getpid()); + sleep(2); + fprintf(stderr,"Child done sleeping... exiting\n"); + _exit(0); + break; + default: + fprintf(stderr,"In the main process (child is: %d) waiting for child\n",pid); + if(waitpid(pid,&status,0) < 0) + perror("waitpid"); + else + fprintf(stderr,"Child process exited (status: %d)\n",status); + } + + pid = fork(); + if(pid==0) { + fprintf(stderr,"1st fork (pid: %d)\n",getpid()); + if(fork()==0) { + fprintf(stderr,"2nd fork (pid: %d).. sleeping\n",getpid()); + sleep(5); + fprintf(stderr,"2nd fork exiting\n"); + _exit(0); + } + _exit(0); + } else { + waitpid(pid,NULL,0); + fprintf(stderr,"1st fork terminated\n"); + } + fprintf(stderr,"Sleeping for a bit\n"); + sleep(10); + fprintf(stderr,"Next few pids should be sequential\n"); + for(i=0;i<10;i++) { + if(fork() == 0) { + fprintf(stderr,"I am a child %d\n",getpid()); + sleep(i%4); + _exit(0); + } + } + for(i=0;i<10;i++) fprintf(stderr,"Waited on %d\n",waitpid(-1,NULL,0)); + + return 0; +} diff --git a/src/tests/FreeTypeDemo.java b/src/tests/FreeTypeDemo.java new file mode 100644 index 0000000..0ac84cd --- /dev/null +++ b/src/tests/FreeTypeDemo.java @@ -0,0 +1,170 @@ +package tests; + +import org.xwt.mips.Runtime; +import org.xwt.mips.Interpreter; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.*; +import java.awt.event.*; +import java.io.*; + +public class FreeTypeDemo { + private JFrame frame; + private static final int OURWIDTH=640; + private static final int OURHEIGHT=256; + private static final int BASELINE=160; + private byte[] render = new byte[OURWIDTH*OURHEIGHT]; + private int size = 72; + private StringBuffer sb = new StringBuffer(); + private View view; + private Image image; + + private Runnable renderThread; + private String theText; + private boolean renderNeeded; + + private String name; + private Runtime rt; + + int renderAddr; + int stringAddr; + int stringSize; + + public static void main(String[] argv) throws Exception { + new FreeTypeDemo(argv); + } + + public FreeTypeDemo(String[] argv) throws Exception { + if(argv.length >= 2 && argv[1].startsWith("int")) { + name = "Interpreter"; + rt = new Interpreter("build/FreeTypeDemoHelper.mips"); + } else { + rt = new FreeTypeDemoHelper(); + name = "Compiler"; + } + + rt.start(new String[]{ "freetype.mips"}); + if(rt.execute()) throw new Error("freetype.mips exited"); + + byte[] font = InputStreamToByteArray.convert(new FileInputStream(argv[0])); + int fontAddr = rt.malloc(font.length); + if(fontAddr == 0) throw new Error("malloc() failed"); + rt.copyout(font,fontAddr,font.length); + + rt.setUserInfo(0,fontAddr); + rt.setUserInfo(1,font.length); + + renderAddr = rt.malloc(OURWIDTH*OURHEIGHT); + if(renderAddr == 0) throw new Error("malloc() failed"); + + if(rt.execute()) throw new Error("freetype.mips exited (" + rt.getUserInfo(1) +")"); + + createImage(); + + frame = new JFrame("FreeTypeDemo - " + name); + frame.setSize(OURWIDTH,OURHEIGHT); + view = new View(); + frame.getContentPane().add(view,BorderLayout.CENTER); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.show(); + view.requestFocus(); + renderThread = new Runnable() { + public void run() { + try { + for(;;) { + synchronized(this) { while(!renderNeeded) wait(); renderNeeded = false; } + renderText(theText==null ? "" : theText); + } + } catch(Exception e) { throw new Error(e); } + } + }; + new Thread(renderThread).start(); + keyPress('\n'); + } + + private static ColorModel cmodel = new DirectColorModel(8, 0xff,0xff,0xff); + private void createImage() { + for(int i=0;i +#include + +FT_Library library; /* handle to library */ +FT_Face face; /* handle to face object */ + +#define FT_Check(expr,err) do { \ + if((expr) != 0) { \ + errprint(#expr " failed\n"); \ + return err; \ + } \ +} while(0) + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +static int errprint(const char *s) { + int l = strlen(s); + int n; + while(l) { + n = write(STDERR_FILENO,s,l); + if(n < 0) return n; + l -= n; + s += n; + } + return 0; +} + +void draw(FT_GlyphSlot glyph,int x, char *buf, int buf_width, int buf_height, int baseline) { + int y = max(baseline - glyph->bitmap_top,0); + int rows = glyph->bitmap.rows; + int width = glyph->bitmap.width; + int i,j; + x = x + glyph->bitmap_left; + if(x + width >= buf_width) return; + if(y + rows >= buf_height) return; + //if(buf == NULL) fprintf(stderr,"ABout to dereference %p\n",buf); + for(i=0;ibitmap.buffer[i*width+j]; +} + +/* Prevent --gc-sections from blowing this away */ +int render(short *s, int size, char *buf, int buf_width, int buf_height, int baseline) __attribute__((section(".text"))); +int render(short *s, int size, char *buf, int buf_width, int buf_height, int baseline) { + int glyph_index; + int x = 0; + FT_Check(FT_Set_Pixel_Sizes(face,0,size),0); + memset(buf,'\0',buf_width*buf_height); + //fprintf(stderr,"Rendering %d pt %c... at %p (%dx%d)\n",size,*s,buf,buf_width,buf_height); + while(*s) { + glyph_index = FT_Get_Char_Index(face,*s); + FT_Check(FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT),0); + FT_Check(FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL/*256color antialiased*/),0); + draw(face->glyph,x,buf,buf_width,buf_height,baseline); + x += face->glyph->advance.x/64; + s++; + } + return 1; +} + +char * user_info[2]; +extern void _pause(); + +int main(int argc,char** argv) { + char *fontdata; + int fontsize; + + _pause(); + + fontdata = user_info[0]; + fontsize = (int)user_info[1]; + + //fprintf(stderr,"Initializng freetype with a %d byte font at %p\n", fontsize, fontdata); + + FT_Check(FT_Init_FreeType(&library),EXIT_FAILURE); + FT_Check(FT_New_Memory_Face(library, fontdata,fontsize, 0, &face),EXIT_FAILURE); + + errprint("Freetype initialized\n"); + _pause(); + errprint("Unpaused\n"); + + /* not reached */ + return EXIT_FAILURE; +} diff --git a/src/tests/Hello.c b/src/tests/Hello.c new file mode 100644 index 0000000..d7189ae --- /dev/null +++ b/src/tests/Hello.c @@ -0,0 +1,6 @@ +#include + +int main() { + puts("Hello, World"); + return 0; +} diff --git a/src/tests/MSPack.java b/src/tests/MSPack.java new file mode 100644 index 0000000..198b7aa --- /dev/null +++ b/src/tests/MSPack.java @@ -0,0 +1,106 @@ +package tests; + +import org.xwt.mips.Runtime; +import java.io.*; + +public class MSPack { + private String[] fileNames; + private int[] lengths; + private byte[][] data; + + public static class MSPackException extends IOException { public MSPackException(String s) { super(s); } } + + public MSPack(InputStream cabIS) throws IOException { + byte[] cab = InputStreamToByteArray.convert(cabIS); + try { + //Interpreter vm = new Interpreter("mspack.mips"); + MSPackHelper vm = new MSPackHelper(); + + int cabAddr = vm.sbrk(cab.length); + if(cabAddr < 0) throw new MSPackException("sbrk failed"); + + vm.copyout(cab,cabAddr,cab.length); + + vm.setUserInfo(0,cabAddr); + vm.setUserInfo(1,cab.length); + + int status = vm.run(new String[]{ "mspack.mips"} ); + if(status != 0) throw new MSPackException("mspack.mips failed (" + status + ")"); + + /*static struct { + char *filename; + char *data; + int length; + } output_table[MAX_MEMBERS+1]; */ + + int filesTable = vm.getUserInfo(2); + int count=0; + while(vm.memRead(filesTable+count*12) != 0) count++; + + fileNames = new String[count]; + data = new byte[count][]; + lengths = new int[count]; + + for(int i=0,addr=filesTable;i +#include +#include +#include +#include + +#include "mspack.h" + +int main(int argc, char **argv) { + struct mscab_decompressor *decomp; + struct mscabd_cabinet *cab; + struct mscabd_file *file; + int i; + + if(argc < 2) { + fprintf(stderr,"Usage: %s cab\n",argv[0]); + exit(1); + } + + + decomp = mspack_create_cab_decompressor(NULL); + if(!decomp) exit(1); + + for(i=1;isearch(decomp,argv[i]); + if(!cab) exit(2); + + for(file = cab->files;file;file=file->next) + decomp->extract(decomp,file,file->filename); + + decomp->close(decomp,cab); + } + mspack_destroy_cab_decompressor(decomp); + + return 0; +} diff --git a/src/tests/MSPackHelper.c b/src/tests/MSPackHelper.c new file mode 100644 index 0000000..ddbcfcf --- /dev/null +++ b/src/tests/MSPackHelper.c @@ -0,0 +1,215 @@ +/* +UserInfo: + On start: + 0: Addr of CAB/EXE + 1: Length of CAB/EXE + On Edit: + 2: Addr of output_table array + +Exit codes: + 0: Success + 1: Internal Error + 2: Invalid CAB +*/ + +#include +#include +#include +#include +#include + +#include "mspack.h" + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX_MEMBERS 64 + +char *xstrdup(const char *s) { + char *ret = strdup(s); + if(ret == NULL) exit(1); + return ret; +} + +typedef struct { + char *addr; + int pos; + int size; + int length; + int writable; +} mem_buf_t; + +static mem_buf_t *cab_mem_buf = NULL; + +static void mem_buf_grow(mem_buf_t *buf,size_t newsize) { + size_t new_len; + char *p; + if(buf->length < 0) exit(1); + if(newsize <= buf->length) return; + new_len = MAX(buf->length ? buf->length*2 : 65536,newsize); + p = realloc(buf->addr,new_len); + if(p == NULL) exit(1); + buf->addr = p; + buf->length = new_len; +} + +static struct { + char *filename; + mem_buf_t buf; +} write_buf_table[MAX_MEMBERS]; + +static struct { + char *filename; + char *data; + int length; +} output_table[MAX_MEMBERS+1]; + +static struct mspack_file *my_open(struct mspack_system *sys, char *filename, int mode) { + mem_buf_t *buf = NULL; + int i; + if(strcmp(filename,"/dev/cab")==0) { + if(mode != MSPACK_SYS_OPEN_READ) return NULL; + buf = cab_mem_buf; + } else { + if(mode != MSPACK_SYS_OPEN_WRITE) return NULL; + + for(i=0;iwritable = 1; + break; + } + } + } + + return (struct mspack_file *) buf; +} + +static void my_close(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + /* NO OP */ +} + +static int my_read(struct mspack_file *buf_, void *out, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + count = MIN(buf->size - buf->pos, count); + memcpy(out,buf->addr + buf->pos,count); + buf->pos += count; + return count; +} + +static int my_write(struct mspack_file *buf_, void *in, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + if(!buf->writable) return -1; + if(buf->length < buf->pos + count) mem_buf_grow(buf,buf->pos + count); + memcpy(buf->addr+buf->pos,in,count); + buf->pos += count; + buf->size = MAX(buf->size,buf->pos); + return count; +} + +static int my_seek(struct mspack_file *buf_, off_t off, int mode) { + mem_buf_t *buf = (mem_buf_t*) buf_; + int newpos; + switch(mode) { + case MSPACK_SYS_SEEK_START: newpos = off; break; + case MSPACK_SYS_SEEK_CUR: newpos = buf->pos + off; break; + case MSPACK_SYS_SEEK_END: newpos = buf->size - off; break; + default: return -1; + } + if(newpos < 0) return -1; + if(newpos > buf->size) { + if(!buf->writable) return -1; + if(newpos > buf->length) + mem_buf_grow(buf,newpos); + } + buf->pos = newpos; + return 0; +} + +static off_t my_tell(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + return buf ? buf->pos : 0; +} + +static void my_message(struct mspack_file *file, char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc((int) '\n', stderr); + fflush(stderr); +} + +static void *my_alloc(struct mspack_system *sys, size_t size) { return malloc(size); } +static void my_free(void *p) { free(p); } +static void my_copy(void *src, void *dest, size_t bytes) { memcpy(dest, src, bytes); } + +static struct mspack_system my_system = { + &my_open, + &my_close, + &my_read, + &my_write, + &my_seek, + &my_tell, + &my_message, + &my_alloc, + &my_free, + &my_copy, + NULL +}; + +char *user_info[4]; + +int main(int argc, char **argv) { + struct mscab_decompressor *decomp; + struct mscabd_cabinet *cab; + struct mscabd_file *file; + mem_buf_t mem_buf; + size_t size = (size_t)user_info[1]; + int i; + + mem_buf.addr = user_info[0]; + mem_buf.pos = mem_buf.writable = 0; + mem_buf.length = -1; + mem_buf.size = size; + + cab_mem_buf = &mem_buf; + + decomp = mspack_create_cab_decompressor(&my_system); + if(!decomp) exit(1); + + cab = decomp->search(decomp,"/dev/cab"); + if(!cab) exit(2); + + for(file = cab->files;file;file=file->next) + decomp->extract(decomp,file,file->filename); + + decomp->close(decomp,cab); + mspack_destroy_cab_decompressor(decomp); + + printf("Success!\n"); + + for(i=0;i +#ifndef NOSIGNAL +#include +#endif +#include + +#ifdef Single +#define FLOAT float +#define FABS(x) (float)fabs((double)(x)) +#define FLOOR(x) (float)floor((double)(x)) +#define LOG(x) (float)log((double)(x)) +#define POW(x,y) (float)pow((double)(x),(double)(y)) +#define SQRT(x) (float)sqrt((double)(x)) +#else +#define FLOAT double +#define FABS(x) fabs(x) +#define FLOOR(x) floor(x) +#define LOG(x) log(x) +#define POW(x,y) pow(x,y) +#define SQRT(x) sqrt(x) +#endif + +jmp_buf ovfl_buf; +#ifdef KR_headers +#define VOID /* void */ +#define INT /* int */ +#define FP /* FLOAT */ +#define CHARP /* char * */ +#define CHARPP /* char ** */ +extern double fabs(), floor(), log(), pow(), sqrt(); +extern void exit(); +typedef void (*Sig_type)(); +FLOAT Sign(), Random(); +extern void BadCond(); +extern void SqXMinX(); +extern void TstCond(); +extern void notify(); +extern int read(); +#else +#define VOID void +#define INT int +#define FP FLOAT +#define CHARP char * +#define CHARPP char ** +#ifdef __STDC__ +#include +#include +#else +#ifdef __cplusplus +extern "C" { +#endif +extern double fabs(double), floor(double), log(double); +extern double pow(double,double), sqrt(double); +extern void exit(INT); +#ifdef __cplusplus + } +#endif +#endif +typedef void (*Sig_type)(int); +FLOAT Sign(FLOAT), Random(void); +extern void BadCond(int, char*); +extern void SqXMinX(int); +extern void TstCond(int, int, char*); +extern void notify(char*); +extern int read(int, char*, int); +#endif +#undef V9 +extern void Characteristics(VOID); +extern void Heading(VOID); +extern void History(VOID); +extern void Instructions(VOID); +extern void IsYeqX(VOID); +extern void NewD(VOID); +extern void Pause(VOID); +extern void PrintIfNPositive(VOID); +extern void SR3750(VOID); +extern void SR3980(VOID); +extern void TstPtUf(VOID); + +Sig_type sigsave; + +#define KEYBOARD 0 + +FLOAT Radix, BInvrse, RadixD2, BMinusU2; + +/*Small floating point constants.*/ +FLOAT Zero = 0.0; +FLOAT Half = 0.5; +FLOAT One = 1.0; +FLOAT Two = 2.0; +FLOAT Three = 3.0; +FLOAT Four = 4.0; +FLOAT Five = 5.0; +FLOAT Eight = 8.0; +FLOAT Nine = 9.0; +FLOAT TwentySeven = 27.0; +FLOAT ThirtyTwo = 32.0; +FLOAT TwoForty = 240.0; +FLOAT MinusOne = -1.0; +FLOAT OneAndHalf = 1.5; +/*Integer constants*/ +int NoTrials = 20; /*Number of tests for commutativity. */ +#define False 0 +#define True 1 + +/* Definitions for declared types + Guard == (Yes, No); + Rounding == (Chopped, Rounded, Other); + Message == packed array [1..40] of char; + Class == (Flaw, Defect, Serious, Failure); + */ +#define Yes 1 +#define No 0 +#define Chopped 2 +#define Rounded 1 +#define Other 0 +#define Flaw 3 +#define Defect 2 +#define Serious 1 +#define Failure 0 +typedef int Guard, Rounding, Class; +typedef char Message; + +/* Declarations of Variables */ +int Indx; +char ch[8]; +FLOAT AInvrse, A1; +FLOAT C, CInvrse; +FLOAT D, FourD; +FLOAT E0, E1, Exp2, E3, MinSqEr; +FLOAT SqEr, MaxSqEr, E9; +FLOAT Third; +FLOAT F6, F9; +FLOAT H, HInvrse; +int I; +FLOAT StickyBit, J; +FLOAT MyZero; +FLOAT Precision; +FLOAT Q, Q9; +FLOAT R, Random9; +FLOAT T, Underflow, S; +FLOAT OneUlp, UfThold, U1, U2; +FLOAT V, V0, V9; +FLOAT W; +FLOAT X, X1, X2, X8, Random1; +FLOAT Y, Y1, Y2, Random2; +FLOAT Z, PseudoZero, Z1, Z2, Z9; +int ErrCnt[4]; +int fpecount; +int Milestone; +int PageNo; +int M, N, N1; +Guard GMult, GDiv, GAddSub; +Rounding RMult, RDiv, RAddSub, RSqrt; +int Break, Done, NotMonot, Monot, Anomaly, IEEE, + SqRWrng, UfNGrad; +/* Computed constants. */ +/*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */ +/*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */ + +/* floating point exception receiver */ + void +sigfpe(INT x) +{ + fpecount++; + printf("\n* * * FLOATING-POINT ERROR %d * * *\n", x); + fflush(stdout); + if (sigsave) { +#ifndef NOSIGNAL + signal(SIGFPE, sigsave); +#endif + sigsave = 0; + longjmp(ovfl_buf, 1); + } + exit(1); +} + +main(VOID) +{ + /* First two assignments use integer right-hand sides. */ + Zero = 0; + One = 1; + Two = One + One; + Three = Two + One; + Four = Three + One; + Five = Four + One; + Eight = Four + Four; + Nine = Three * Three; + TwentySeven = Nine * Three; + ThirtyTwo = Four * Eight; + TwoForty = Four * Five * Three * Four; + MinusOne = -One; + Half = One / Two; + OneAndHalf = One + Half; + ErrCnt[Failure] = 0; + ErrCnt[Serious] = 0; + ErrCnt[Defect] = 0; + ErrCnt[Flaw] = 0; + PageNo = 1; + /*=============================================*/ + Milestone = 0; + /*=============================================*/ +#ifndef NOSIGNAL + signal(SIGFPE, sigfpe); +#endif + Instructions(); + Pause(); + Heading(); + Pause(); + Characteristics(); + Pause(); + History(); + Pause(); + /*=============================================*/ + Milestone = 7; + /*=============================================*/ + printf("Program is now RUNNING tests on small integers:\n"); + + TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero) + && (One > Zero) && (One + One == Two), + "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2"); + Z = - Zero; + if (Z != 0.0) { + ErrCnt[Failure] = ErrCnt[Failure] + 1; + printf("Comparison alleges that -0.0 is Non-zero!\n"); + U2 = 0.001; + Radix = 1; + TstPtUf(); + } + TstCond (Failure, (Three == Two + One) && (Four == Three + One) + && (Four + Two * (- Two) == Zero) + && (Four - Three - One == Zero), + "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0"); + TstCond (Failure, (MinusOne == (0 - One)) + && (MinusOne + One == Zero ) && (One + MinusOne == Zero) + && (MinusOne + FABS(One) == Zero) + && (MinusOne + MinusOne * MinusOne == Zero), + "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0"); + TstCond (Failure, Half + MinusOne + Half == Zero, + "1/2 + (-1) + 1/2 != 0"); + /*=============================================*/ + /*SPLIT + { + extern void part2(VOID), part3(VOID), part4(VOID), + part5(VOID), part6(VOID), part7(VOID); + int part8(VOID); + + part2(); + part3(); + part4(); + part5(); + part6(); + part7(); + return part8(); + } + } +#include "paranoia.h" +void part2(VOID){ +*/ + Milestone = 10; + /*=============================================*/ + TstCond (Failure, (Nine == Three * Three) + && (TwentySeven == Nine * Three) && (Eight == Four + Four) + && (ThirtyTwo == Eight * Four) + && (ThirtyTwo - TwentySeven - Four - One == Zero), + "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0"); + TstCond (Failure, (Five == Four + One) && + (TwoForty == Four * Five * Three * Four) + && (TwoForty / Three - Four * Four * Five == Zero) + && ( TwoForty / Four - Five * Three * Four == Zero) + && ( TwoForty / Five - Four * Three * Four == Zero), + "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48"); + if (ErrCnt[Failure] == 0) { + printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n"); + printf("\n"); + } + printf("Searching for Radix and Precision.\n"); + W = One; + do { + W = W + W; + Y = W + One; + Z = Y - W; + Y = Z - One; + } while (MinusOne + FABS(Y) < Zero); + /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/ + Precision = Zero; + Y = One; + do { + Radix = W + Y; + Y = Y + Y; + Radix = Radix - W; + } while ( Radix == Zero); + if (Radix < Two) Radix = One; + printf("Radix = %f .\n", Radix); + if (Radix != 1) { + W = One; + do { + Precision = Precision + One; + W = W * Radix; + Y = W + One; + } while ((Y - W) == One); + } + /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 + ...*/ + U1 = One / W; + U2 = Radix * U1; + printf("Closest relative separation found is U1 = %.7e .\n\n", U1); + printf("Recalculating radix and precision\n "); + + /*save old values*/ + E0 = Radix; + E1 = U1; + E9 = U2; + E3 = Precision; + + X = Four / Three; + Third = X - One; + F6 = Half - Third; + X = F6 + F6; + X = FABS(X - Third); + if (X < U2) X = U2; + + /*... now X = (unknown no.) ulps of 1+...*/ + do { + U2 = X; + Y = Half * U2 + ThirtyTwo * U2 * U2; + Y = One + Y; + X = Y - One; + } while ( ! ((U2 <= X) || (X <= Zero))); + + /*... now U2 == 1 ulp of 1 + ... */ + X = Two / Three; + F6 = X - Half; + Third = F6 + F6; + X = Third - Half; + X = FABS(X + F6); + if (X < U1) X = U1; + + /*... now X == (unknown no.) ulps of 1 -... */ + do { + U1 = X; + Y = Half * U1 + ThirtyTwo * U1 * U1; + Y = Half - Y; + X = Half + Y; + Y = Half - X; + X = Half + Y; + } while ( ! ((U1 <= X) || (X <= Zero))); + /*... now U1 == 1 ulp of 1 - ... */ + if (U1 == E1) printf("confirms closest relative separation U1 .\n"); + else printf("gets better closest relative separation U1 = %.7e .\n", U1); + W = One / U1; + F9 = (Half - U1) + Half; + Radix = FLOOR(0.01 + U2 / U1); + if (Radix == E0) printf("Radix confirmed.\n"); + else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix); + TstCond (Defect, Radix <= Eight + Eight, + "Radix is too big: roundoff problems"); + TstCond (Flaw, (Radix == Two) || (Radix == 10) + || (Radix == One), "Radix is not as good as 2 or 10"); + /*=============================================*/ + Milestone = 20; + /*=============================================*/ + TstCond (Failure, F9 - Half < Half, + "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?"); + X = F9; + I = 1; + Y = X - Half; + Z = Y - Half; + TstCond (Failure, (X != One) + || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0"); + X = One + U2; + I = 0; + /*=============================================*/ + Milestone = 25; + /*=============================================*/ + /*... BMinusU2 = nextafter(Radix, 0) */ + BMinusU2 = Radix - One; + BMinusU2 = (BMinusU2 - U2) + One; + /* Purify Integers */ + if (Radix != One) { + X = - TwoForty * LOG(U1) / LOG(Radix); + Y = FLOOR(Half + X); + if (FABS(X - Y) * Four < One) X = Y; + Precision = X / TwoForty; + Y = FLOOR(Half + Precision); + if (FABS(Precision - Y) * TwoForty < Half) Precision = Y; + } + if ((Precision != FLOOR(Precision)) || (Radix == One)) { + printf("Precision cannot be characterized by an Integer number\n"); + printf("of significant digits but, by itself, this is a minor flaw.\n"); + } + if (Radix == One) + printf("logarithmic encoding has precision characterized solely by U1.\n"); + else printf("The number of significant digits of the Radix is %f .\n", + Precision); + TstCond (Serious, U2 * Nine * Nine * TwoForty < One, + "Precision worse than 5 decimal figures "); + /*=============================================*/ + Milestone = 30; + /*=============================================*/ + /* Test for extra-precise subepressions */ + X = FABS(((Four / Three - One) - One / Four) * Three - One / Four); + do { + Z2 = X; + X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One; + } while ( ! ((Z2 <= X) || (X <= Zero))); + X = Y = Z = FABS((Three / Four - Two / Three) * Three - One / Four); + do { + Z1 = Z; + Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1)) + + One / Two)) + One / Two; + } while ( ! ((Z1 <= Z) || (Z <= Zero))); + do { + do { + Y1 = Y; + Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half + )) + Half; + } while ( ! ((Y1 <= Y) || (Y <= Zero))); + X1 = X; + X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9; + } while ( ! ((X1 <= X) || (X <= Zero))); + if ((X1 != Y1) || (X1 != Z1)) { + BadCond(Serious, "Disagreements among the values X1, Y1, Z1,\n"); + printf("respectively %.7e, %.7e, %.7e,\n", X1, Y1, Z1); + printf("are symptoms of inconsistencies introduced\n"); + printf("by extra-precise evaluation of arithmetic subexpressions.\n"); + notify("Possibly some part of this"); + if ((X1 == U1) || (Y1 == U1) || (Z1 == U1)) printf( + "That feature is not tested further by this program.\n") ; + } + else { + if ((Z1 != U1) || (Z2 != U2)) { + if ((Z1 >= U1) || (Z2 >= U2)) { + BadCond(Failure, ""); + notify("Precision"); + printf("\tU1 = %.7e, Z1 - U1 = %.7e\n",U1,Z1-U1); + printf("\tU2 = %.7e, Z2 - U2 = %.7e\n",U2,Z2-U2); + } + else { + if ((Z1 <= Zero) || (Z2 <= Zero)) { + printf("Because of unusual Radix = %f", Radix); + printf(", or exact rational arithmetic a result\n"); + printf("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2); + notify("of an\nextra-precision"); + } + if (Z1 != Z2 || Z1 > Zero) { + X = Z1 / U1; + Y = Z2 / U2; + if (Y > X) X = Y; + Q = - LOG(X); + printf("Some subexpressions appear to be calculated extra\n"); + printf("precisely with about %g extra B-digits, i.e.\n", + (Q / LOG(Radix))); + printf("roughly %g extra significant decimals.\n", + Q / LOG(10.)); + } + printf("That feature is not tested further by this program.\n"); + } + } + } + Pause(); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +void part3(VOID){ +*/ + Milestone = 35; + /*=============================================*/ + if (Radix >= Two) { + X = W / (Radix * Radix); + Y = X + One; + Z = Y - X; + T = Z + U2; + X = T - Z; + TstCond (Failure, X == U2, + "Subtraction is not normalized X=Y,X+Z != Y+Z!"); + if (X == U2) printf( + "Subtraction appears to be normalized, as it should be."); + } + printf("\nChecking for guard digit in *, /, and -.\n"); + Y = F9 * One; + Z = One * F9; + X = F9 - Half; + Y = (Y - Half) - X; + Z = (Z - Half) - X; + X = One + U2; + T = X * Radix; + R = Radix * X; + X = T - Radix; + X = X - Radix * U2; + T = R - Radix; + T = T - Radix * U2; + X = X * (Radix - One); + T = T * (Radix - One); + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) GMult = Yes; + else { + GMult = No; + TstCond (Serious, False, + "* lacks a Guard Digit, so 1*X != X"); + } + Z = Radix * U2; + X = One + Z; + Y = FABS((X + Z) - X * X) - U2; + X = One - U2; + Z = FABS((X - U2) - X * X) - U1; + TstCond (Failure, (Y <= Zero) + && (Z <= Zero), "* gets too many final digits wrong.\n"); + Y = One - U2; + X = One + U2; + Z = One / Y; + Y = Z - X; + X = One / Three; + Z = Three / Nine; + X = X - Z; + T = Nine / TwentySeven; + Z = Z - T; + TstCond(Defect, X == Zero && Y == Zero && Z == Zero, + "Division lacks a Guard Digit, so error can exceed 1 ulp\n\ +or 1/3 and 3/9 and 9/27 may disagree"); + Y = F9 / One; + X = F9 - Half; + Y = (Y - Half) - X; + X = One + U2; + T = X / One; + X = T - X; + if ((X == Zero) && (Y == Zero) && (Z == Zero)) GDiv = Yes; + else { + GDiv = No; + TstCond (Serious, False, + "Division lacks a Guard Digit, so X/1 != X"); + } + X = One / (One + U2); + Y = X - Half - Half; + TstCond (Serious, Y < Zero, + "Computed value of 1/1.000..1 >= 1"); + X = One - U2; + Y = One + Radix * U2; + Z = X * Radix; + T = Y * Radix; + R = Z / Radix; + StickyBit = T / Radix; + X = R - X; + Y = StickyBit - Y; + TstCond (Failure, X == Zero && Y == Zero, + "* and/or / gets too many last digits wrong"); + Y = One - U1; + X = One - F9; + Y = One - Y; + T = Radix - U2; + Z = Radix - BMinusU2; + T = Radix - T; + if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) GAddSub = Yes; + else { + GAddSub = No; + TstCond (Serious, False, + "- lacks Guard Digit, so cancellation is obscured"); + } + if (F9 != One && F9 - One >= Zero) { + BadCond(Serious, "comparison alleges (1-U1) < 1 although\n"); + printf(" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n"); + printf(" such precautions against division by zero as\n"); + printf(" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); + } + if (GMult == Yes && GDiv == Yes && GAddSub == Yes) printf( + " *, /, and - appear to have guard digits, as they should.\n"); + /*=============================================*/ + Milestone = 40; + /*=============================================*/ + Pause(); + printf("Checking rounding on multiply, divide and add/subtract.\n"); + RMult = Other; + RDiv = Other; + RAddSub = Other; + RadixD2 = Radix / Two; + A1 = Two; + Done = False; + do { + AInvrse = Radix; + do { + X = AInvrse; + AInvrse = AInvrse / A1; + } while ( ! (FLOOR(AInvrse) != AInvrse)); + Done = (X == One) || (A1 > Three); + if (! Done) A1 = Nine + One; + } while ( ! (Done)); + if (X == One) A1 = Radix; + AInvrse = One / A1; + X = A1; + Y = AInvrse; + Done = False; + do { + Z = X * Y - Half; + TstCond (Failure, Z == Half, + "X * (1/X) differs from 1"); + Done = X == Radix; + X = Radix; + Y = One / X; + } while ( ! (Done)); + Y2 = One + U2; + Y1 = One - U2; + X = OneAndHalf - U2; + Y = OneAndHalf + U2; + Z = (X - U2) * Y2; + T = Y * Y1; + Z = Z - X; + T = T - X; + X = X * Y2; + Y = (Y + U2) * Y1; + X = X - OneAndHalf; + Y = Y - OneAndHalf; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) { + X = (OneAndHalf + U2) * Y2; + Y = OneAndHalf - U2 - U2; + Z = OneAndHalf + U2 + U2; + T = (OneAndHalf - U2) * Y1; + X = X - (Z + U2); + StickyBit = Y * Y1; + S = Z * Y2; + T = T - Y; + Y = (U2 - Y) + StickyBit; + Z = S - (Z + U2 + U2); + StickyBit = (Y2 + U2) * Y1; + Y1 = Y2 * Y1; + StickyBit = StickyBit - Y2; + Y1 = Y1 - Half; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) + && ( StickyBit == Zero) && (Y1 == Half)) { + RMult = Rounded; + printf("Multiplication appears to round correctly.\n"); + } + else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero) + && (T < Zero) && (StickyBit + U2 == Zero) + && (Y1 < Half)) { + RMult = Chopped; + printf("Multiplication appears to chop.\n"); + } + else printf("* is neither chopped nor correctly rounded.\n"); + if ((RMult == Rounded) && (GMult == No)) notify("Multiplication"); + } + else printf("* is neither chopped nor correctly rounded.\n"); + /*=============================================*/ + Milestone = 45; + /*=============================================*/ + Y2 = One + U2; + Y1 = One - U2; + Z = OneAndHalf + U2 + U2; + X = Z / Y2; + T = OneAndHalf - U2 - U2; + Y = (T - U2) / Y1; + Z = (Z + U2) / Y2; + X = X - OneAndHalf; + Y = Y - T; + T = T / Y1; + Z = Z - (OneAndHalf + U2); + T = (U2 - OneAndHalf) + T; + if (! ((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) { + X = OneAndHalf / Y2; + Y = OneAndHalf - U2; + Z = OneAndHalf + U2; + X = X - Y; + T = OneAndHalf / Y1; + Y = Y / Y1; + T = T - (Z + U2); + Y = Y - Z; + Z = Z / Y2; + Y1 = (Y2 + U2) / Y2; + Z = Z - OneAndHalf; + Y2 = Y1 - Y2; + Y1 = (F9 - U1) / F9; + if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) + && (Y2 == Zero) && (Y2 == Zero) + && (Y1 - Half == F9 - Half )) { + RDiv = Rounded; + printf("Division appears to round correctly.\n"); + if (GDiv == No) notify("Division"); + } + else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero) + && (Y2 < Zero) && (Y1 - Half < F9 - Half)) { + RDiv = Chopped; + printf("Division appears to chop.\n"); + } + } + if (RDiv == Other) printf("/ is neither chopped nor correctly rounded.\n"); + BInvrse = One / Radix; + TstCond (Failure, (BInvrse * Radix - Half == Half), + "Radix * ( 1 / Radix ) differs from 1"); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +void part4(VOID){ +*/ + Milestone = 50; + /*=============================================*/ + TstCond (Failure, ((F9 + U1) - Half == Half) + && ((BMinusU2 + U2 ) - One == Radix - One), + "Incomplete carry-propagation in Addition"); + X = One - U1 * U1; + Y = One + U2 * (One - U2); + Z = F9 - Half; + X = (X - Half) - Z; + Y = Y - One; + if ((X == Zero) && (Y == Zero)) { + RAddSub = Chopped; + printf("Add/Subtract appears to be chopped.\n"); + } + if (GAddSub == Yes) { + X = (Half + U2) * U2; + Y = (Half - U2) * U2; + X = One + X; + Y = One + Y; + X = (One + U2) - X; + Y = One - Y; + if ((X == Zero) && (Y == Zero)) { + X = (Half + U2) * U1; + Y = (Half - U2) * U1; + X = One - X; + Y = One - Y; + X = F9 - X; + Y = One - Y; + if ((X == Zero) && (Y == Zero)) { + RAddSub = Rounded; + printf("Addition/Subtraction appears to round correctly.\n"); + if (GAddSub == No) notify("Add/Subtract"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + } + else printf("Addition/Subtraction neither rounds nor chops.\n"); + S = One; + X = One + Half * (One + Half); + Y = (One + U2) * Half; + Z = X - Y; + T = Y - X; + StickyBit = Z + T; + if (StickyBit != Zero) { + S = Zero; + BadCond(Flaw, "(X - Y) + (Y - X) is non zero!\n"); + } + StickyBit = Zero; + if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes) + && (RMult == Rounded) && (RDiv == Rounded) + && (RAddSub == Rounded) && (FLOOR(RadixD2) == RadixD2)) { + printf("Checking for sticky bit.\n"); + X = (Half + U1) * U2; + Y = Half * U2; + Z = One + Y; + T = One + X; + if ((Z - One <= Zero) && (T - One >= U2)) { + Z = T + Y; + Y = Z - X; + if ((Z - T >= U2) && (Y - T == Zero)) { + X = (Half + U1) * U1; + Y = Half * U1; + Z = One - Y; + T = One - X; + if ((Z - One == Zero) && (T - F9 == Zero)) { + Z = (Half - U1) * U1; + T = F9 - Z; + Q = F9 - Y; + if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) { + Z = (One + U2) * OneAndHalf; + T = (OneAndHalf + U2) - Z + U2; + X = One + Half / Radix; + Y = One + Radix * U2; + Z = X * Y; + if (T == Zero && X + Radix * U2 - Z == Zero) { + if (Radix != Two) { + X = Two + U2; + Y = X / Two; + if ((Y - One == Zero)) StickyBit = S; + } + else StickyBit = S; + } + } + } + } + } + } + if (StickyBit == One) printf("Sticky bit apparently used correctly.\n"); + else printf("Sticky bit used incorrectly or not at all.\n"); + TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No || + RMult == Other || RDiv == Other || RAddSub == Other), + "lack(s) of guard digits or failure(s) to correctly round or chop\n\ +(noted above) count as one flaw in the final tally below"); + /*=============================================*/ + Milestone = 60; + /*=============================================*/ + printf("\n"); + printf("Does Multiplication commute? "); + printf("Testing on %d random pairs.\n", NoTrials); + Random9 = SQRT(3.0); + Random1 = Third; + I = 1; + do { + X = Random(); + Y = Random(); + Z9 = Y * X; + Z = X * Y; + Z9 = Z - Z9; + I = I + 1; + } while ( ! ((I > NoTrials) || (Z9 != Zero))); + if (I == NoTrials) { + Random1 = One + Half / Three; + Random2 = (U2 + U1) + One; + Z = Random1 * Random2; + Y = Random2 * Random1; + Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half / + Three) * ((U2 + U1) + One); + } + if (! ((I == NoTrials) || (Z9 == Zero))) + BadCond(Defect, "X * Y == Y * X trial fails.\n"); + else printf(" No failures found in %d integer pairs.\n", NoTrials); + /*=============================================*/ + Milestone = 70; + /*=============================================*/ + printf("\nRunning test of square root(x).\n"); + TstCond (Failure, (Zero == SQRT(Zero)) + && (- Zero == SQRT(- Zero)) + && (One == SQRT(One)), "Square root of 0.0, -0.0 or 1.0 wrong"); + MinSqEr = Zero; + MaxSqEr = Zero; + J = Zero; + X = Radix; + OneUlp = U2; + SqXMinX (Serious); + X = BInvrse; + OneUlp = BInvrse * U1; + SqXMinX (Serious); + X = U1; + OneUlp = U1 * U1; + SqXMinX (Serious); + if (J != Zero) Pause(); + printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials); + J = Zero; + X = Two; + Y = Radix; + if ((Radix != One)) do { + X = Y; + Y = Radix * Y; + } while ( ! ((Y - X >= NoTrials))); + OneUlp = X * U2; + I = 1; + while (I <= NoTrials) { + X = X + One; + SqXMinX (Defect); + if (J > Zero) break; + I = I + 1; + } + printf("Test for sqrt monotonicity.\n"); + I = - 1; + X = BMinusU2; + Y = Radix; + Z = Radix + Radix * U2; + NotMonot = False; + Monot = False; + while ( ! (NotMonot || Monot)) { + I = I + 1; + X = SQRT(X); + Q = SQRT(Y); + Z = SQRT(Z); + if ((X > Q) || (Q > Z)) NotMonot = True; + else { + Q = FLOOR(Q + Half); + if (!(I > 0 || Radix == Q * Q)) Monot = True; + else if (I > 0) { + if (I > 1) Monot = True; + else { + Y = Y * BInvrse; + X = Y - U1; + Z = Y + U1; + } + } + else { + Y = Q; + X = Y - U2; + Z = Y + U2; + } + } + } + if (Monot) printf("sqrt has passed a test for Monotonicity.\n"); + else { + BadCond(Defect, ""); + printf("sqrt(X) is non-monotonic for X near %.7e .\n", Y); + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +void part5(VOID){ +*/ + Milestone = 80; + /*=============================================*/ + MinSqEr = MinSqEr + Half; + MaxSqEr = MaxSqEr - Half; + Y = (SQRT(One + U2) - One) / U2; + SqEr = (Y - One) + U2 / Eight; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + SqEr = Y + U2 / Eight; + if (SqEr < MinSqEr) MinSqEr = SqEr; + Y = ((SQRT(F9) - U2) - (One - U2)) / U1; + SqEr = Y + U1 / Eight; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + SqEr = (Y + One) + U1 / Eight; + if (SqEr < MinSqEr) MinSqEr = SqEr; + OneUlp = U2; + X = OneUlp; + for( Indx = 1; Indx <= 3; ++Indx) { + Y = SQRT((X + U1 + X) + F9); + Y = ((Y - U2) - ((One - U2) + X)) / OneUlp; + Z = ((U1 - X) + F9) * Half * X * X / OneUlp; + SqEr = (Y + Half) + Z; + if (SqEr < MinSqEr) MinSqEr = SqEr; + SqEr = (Y - Half) + Z; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + if (((Indx == 1) || (Indx == 3))) + X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp))); + else { + OneUlp = U1; + X = - OneUlp; + } + } + /*=============================================*/ + Milestone = 85; + /*=============================================*/ + SqRWrng = False; + Anomaly = False; + RSqrt = Other; /* ~dgh */ + if (Radix != One) { + printf("Testing whether sqrt is rounded or chopped.\n"); + D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision))); + /* ... == Radix^(1 + fract) if (Precision == Integer + fract. */ + X = D / Radix; + Y = D / A1; + if ((X != FLOOR(X)) || (Y != FLOOR(Y))) { + Anomaly = True; + } + else { + X = Zero; + Z2 = X; + Y = One; + Y2 = Y; + Z1 = Radix - One; + FourD = Four * D; + do { + if (Y2 > Z2) { + Q = Radix; + Y1 = Y; + do { + X1 = FABS(Q + FLOOR(Half - Q / Y1) * Y1); + Q = Y1; + Y1 = X1; + } while ( ! (X1 <= Zero)); + if (Q <= One) { + Z2 = Y2; + Z = Y; + } + } + Y = Y + Two; + X = X + Eight; + Y2 = Y2 + X; + if (Y2 >= FourD) Y2 = Y2 - FourD; + } while ( ! (Y >= D)); + X8 = FourD - Z2; + Q = (X8 + Z * Z) / FourD; + X8 = X8 / Eight; + if (Q != FLOOR(Q)) Anomaly = True; + else { + Break = False; + do { + X = Z1 * Z; + X = X - FLOOR(X / Radix) * Radix; + if (X == One) + Break = True; + else + Z1 = Z1 - One; + } while ( ! (Break || (Z1 <= Zero))); + if ((Z1 <= Zero) && (! Break)) Anomaly = True; + else { + if (Z1 > RadixD2) Z1 = Z1 - Radix; + do { + NewD(); + } while ( ! (U2 * D >= F9)); + if (D * Radix - D != W - D) Anomaly = True; + else { + Z2 = D; + I = 0; + Y = D + (One + Z) * Half; + X = D + Z + Q; + SR3750(); + Y = D + (One - Z) * Half + D; + X = D - Z + D; + X = X + Q + X; + SR3750(); + NewD(); + if (D - Z2 != W - Z2) Anomaly = True; + else { + Y = (D - Z2) + (Z2 + (One - Z) * Half); + X = (D - Z2) + (Z2 - Z + Q); + SR3750(); + Y = (One + Z) * Half; + X = Q; + SR3750(); + if (I == 0) Anomaly = True; + } + } + } + } + } + if ((I == 0) || Anomaly) { + BadCond(Failure, "Anomalous arithmetic with Integer < "); + printf("Radix^Precision = %.7e\n", W); + printf(" fails test whether sqrt rounds or chops.\n"); + SqRWrng = True; + } + } + if (! Anomaly) { + if (! ((MinSqEr < Zero) || (MaxSqEr > Zero))) { + RSqrt = Rounded; + printf("Square root appears to be correctly rounded.\n"); + } + else { + if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half) + || (MinSqEr + Radix < Half)) SqRWrng = True; + else { + RSqrt = Chopped; + printf("Square root appears to be chopped.\n"); + } + } + } + if (SqRWrng) { + printf("Square root is neither chopped nor correctly rounded.\n"); + printf("Observed errors run from %.7e ", MinSqEr - Half); + printf("to %.7e ulps.\n", Half + MaxSqEr); + TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix, + "sqrt gets too many last digits wrong"); + } + /*=============================================*/ + Milestone = 90; + /*=============================================*/ + Pause(); + printf("Testing powers Z^i for small Integers Z and i.\n"); + N = 0; + /* ... test powers of zero. */ + I = 0; + Z = -Zero; + M = 3; + Break = False; + do { + X = One; + SR3980(); + if (I <= 10) { + I = 1023; + SR3980(); + } + if (Z == MinusOne) Break = True; + else { + Z = MinusOne; + /* .. if(-1)^N is invalid, replace MinusOne by One. */ + I = - 4; + } + } while ( ! Break); + PrintIfNPositive(); + N1 = N; + N = 0; + Z = A1; + M = (int)FLOOR(Two * LOG(W) / LOG(A1)); + Break = False; + do { + X = Z; + I = 1; + SR3980(); + if (Z == AInvrse) Break = True; + else Z = AInvrse; + } while ( ! (Break)); + /*=============================================*/ + Milestone = 100; + /*=============================================*/ + /* Powers of Radix have been tested, */ + /* next try a few primes */ + M = NoTrials; + Z = Three; + do { + X = Z; + I = 1; + SR3980(); + do { + Z = Z + Two; + } while ( Three * FLOOR(Z / Three) == Z ); + } while ( Z < Eight * Three ); + if (N > 0) { + printf("Errors like this may invalidate financial calculations\n"); + printf("\tinvolving interest rates.\n"); + } + PrintIfNPositive(); + N += N1; + if (N == 0) printf("... no discrepancies found.\n"); + if (N > 0) Pause(); + else printf("\n"); + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +void part6(VOID){ +*/ + Milestone = 110; + /*=============================================*/ + printf("Seeking Underflow thresholds UfThold and E0.\n"); + D = U1; + if (Precision != FLOOR(Precision)) { + D = BInvrse; + X = Precision; + do { + D = D * BInvrse; + X = X - One; + } while ( X > Zero); + } + Y = One; + Z = D; + /* ... D is power of 1/Radix < 1. */ + do { + C = Y; + Y = Z; + Z = Y * Y; + } while ((Y > Z) && (Z + Z > Z)); + Y = C; + Z = Y * D; + do { + C = Y; + Y = Z; + Z = Y * D; + } while ((Y > Z) && (Z + Z > Z)); + if (Radix < Two) HInvrse = Two; + else HInvrse = Radix; + H = One / HInvrse; + /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */ + CInvrse = One / C; + E0 = C; + Z = E0 * H; + /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */ + do { + Y = E0; + E0 = Z; + Z = E0 * H; + } while ((E0 > Z) && (Z + Z > Z)); + UfThold = E0; + E1 = Zero; + Q = Zero; + E9 = U2; + S = One + E9; + D = C * S; + if (D <= C) { + E9 = Radix * U2; + S = One + E9; + D = C * S; + if (D <= C) { + BadCond(Failure, "multiplication gets too many last digits wrong.\n"); + Underflow = E0; + Y1 = Zero; + PseudoZero = Z; + Pause(); + } + } + else { + Underflow = D; + PseudoZero = Underflow * H; + UfThold = Zero; + do { + Y1 = Underflow; + Underflow = PseudoZero; + if (E1 + E1 <= E1) { + Y2 = Underflow * HInvrse; + E1 = FABS(Y1 - Y2); + Q = Y1; + if ((UfThold == Zero) && (Y1 != Y2)) UfThold = Y1; + } + PseudoZero = PseudoZero * H; + } while ((Underflow > PseudoZero) + && (PseudoZero + PseudoZero > PseudoZero)); + } + /* Comment line 4530 .. 4560 */ + if (PseudoZero != Zero) { + printf("\n"); + Z = PseudoZero; + /* ... Test PseudoZero for "phoney- zero" violates */ + /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero + ... */ + if (PseudoZero <= Zero) { + BadCond(Failure, "Positive expressions can underflow to an\n"); + printf("allegedly negative value\n"); + printf("PseudoZero that prints out as: %g .\n", PseudoZero); + X = - PseudoZero; + if (X <= Zero) { + printf("But -PseudoZero, which should be\n"); + printf("positive, isn't; it prints out as %g .\n", X); + } + } + else { + BadCond(Flaw, "Underflow can stick at an allegedly positive\n"); + printf("value PseudoZero that prints out as %g .\n", PseudoZero); + } + TstPtUf(); + } + /*=============================================*/ + Milestone = 120; + /*=============================================*/ + if (CInvrse * Y > CInvrse * Y1) { + S = H * S; + E0 = Underflow; + } + if (! ((E1 == Zero) || (E1 == E0))) { + BadCond(Defect, ""); + if (E1 < E0) { + printf("Products underflow at a higher"); + printf(" threshold than differences.\n"); + if (PseudoZero == Zero) + E0 = E1; + } + else { + printf("Difference underflows at a higher"); + printf(" threshold than products.\n"); + } + } + printf("Smallest strictly positive number found is E0 = %g .\n", E0); + Z = E0; + TstPtUf(); + Underflow = E0; + if (N == 1) Underflow = Y; + I = 4; + if (E1 == Zero) I = 3; + if (UfThold == Zero) I = I - 2; + UfNGrad = True; + switch (I) { + case 1: + UfThold = Underflow; + if ((CInvrse * Q) != ((CInvrse * Y) * S)) { + UfThold = Y; + BadCond(Failure, "Either accuracy deteriorates as numbers\n"); + printf("approach a threshold = %.17e\n", UfThold);; + printf(" coming down from %.17e\n", C); + printf(" or else multiplication gets too many last digits wrong.\n"); + } + Pause(); + break; + + case 2: + BadCond(Failure, "Underflow confuses Comparison, which alleges that\n"); + printf("Q == Y while denying that |Q - Y| == 0; these values\n"); + printf("print out as Q = %.17e, Y = %.17e .\n", Q, Y2); + printf ("|Q - Y| = %.17e .\n" , FABS(Q - Y2)); + UfThold = Q; + break; + + case 3: + X = X; + break; + + case 4: + if ((Q == UfThold) && (E1 == E0) + && (FABS( UfThold - E1 / E9) <= E1)) { + UfNGrad = False; + printf("Underflow is gradual; it incurs Absolute Error =\n"); + printf("(roundoff in UfThold) < E0.\n"); + Y = E0 * CInvrse; + Y = Y * (OneAndHalf + U2); + X = CInvrse * (One + U2); + Y = Y / X; + IEEE = (Y == E0); + } + } + if (UfNGrad) { + printf("\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) { + printf("Underflow / UfThold failed!\n"); + R = H + H; + } + else R = SQRT(Underflow / UfThold); + sigsave = 0; + if (R <= H) { + Z = R * UfThold; + X = Z * (One + R * H * (One + H)); + } + else { + Z = UfThold; + X = Z * (One + H * H * (One + H)); + } + if (! ((X == Z) || (X - Z != Zero))) { + BadCond(Flaw, ""); + printf("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z); + Z9 = X - Z; + printf("yet X - Z yields %.17e .\n", Z9); + printf(" Should this NOT signal Underflow, "); + printf("this is a SERIOUS DEFECT\nthat causes "); + printf("confusion when innocent statements like\n");; + printf(" if (X == Z) ... else"); + printf(" ... (f(X) - f(Z)) / (X - Z) ...\n"); + printf("encounter Division by Zero although actually\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) printf("X / Z fails!\n"); + else printf("X / Z = 1 + %g .\n", (X / Z - Half) - Half); + sigsave = 0; + } + } + printf("The Underflow threshold is %.17e, %s\n", UfThold, + " below which"); + printf("calculation may suffer larger Relative error than "); + printf("merely roundoff.\n"); + Y2 = U1 * U1; + Y = Y2 * Y2; + Y2 = Y * U1; + if (Y2 <= UfThold) { + if (Y > E0) { + BadCond(Defect, ""); + I = 5; + } + else { + BadCond(Serious, ""); + I = 4; + } + printf("Range is too narrow; U1^%d Underflows.\n", I); + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +void part7(VOID){ +*/ + Milestone = 130; + /*=============================================*/ + Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty; + Y2 = Y + Y; + printf("Since underflow occurs below the threshold\n"); + printf("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y); + printf("should afflict the expression\n\t(%.17e) ^ (%.17e);\n", + HInvrse, Y2); + printf("actually calculating yields:"); + if (setjmp(ovfl_buf)) { + sigsave = 0; + BadCond(Serious, "trap on underflow.\n"); + } + else { + sigsave = sigfpe; + V9 = POW(HInvrse, Y2); + sigsave = 0; + printf(" %.17e .\n", V9); + if (! ((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) { + BadCond(Serious, "this is not between 0 and underflow\n"); + printf(" threshold = %.17e .\n", UfThold); + } + else if (! (V9 > UfThold * (One + E9))) + printf("This computed value is O.K.\n"); + else { + BadCond(Defect, "this is not between 0 and underflow\n"); + printf(" threshold = %.17e .\n", UfThold); + } + } + /*=============================================*/ + Milestone = 140; + /*=============================================*/ + printf("\n"); + /* ...calculate Exp2 == exp(2) == 7.389056099... */ + X = Zero; + I = 2; + Y = Two * Three; + Q = Zero; + N = 0; + do { + Z = X; + I = I + 1; + Y = Y / (I + I); + R = Y + Q; + X = Z + R; + Q = (Z - X) + R; + } while(X > Z); + Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo); + X = Z * Z; + Exp2 = X * X; + X = F9; + Y = X - U1; + printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n", + Exp2); + for(I = 1;;) { + Z = X - BInvrse; + Z = (X + One) / (Z - (One - BInvrse)); + Q = POW(X, Z) - Exp2; + if (FABS(Q) > TwoForty * U2) { + N = 1; + V9 = (X - BInvrse) - (One - BInvrse); + BadCond(Defect, "Calculated"); + printf(" %.17e for\n", POW(X,Z)); + printf("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z); + printf("\tdiffers from correct value by %.17e .\n", Q); + printf("\tThis much error may spoil financial\n"); + printf("\tcalculations involving tiny interest rates.\n"); + break; + } + else { + Z = (Y - X) * Two + Y; + X = Y; + Y = Z; + Z = One + (X - F9)*(X - F9); + if (Z > One && I < NoTrials) I++; + else { + if (X > One) { + if (N == 0) + printf("Accuracy seems adequate.\n"); + break; + } + else { + X = One + U2; + Y = U2 + U2; + Y += X; + I = 1; + } + } + } + } + /*=============================================*/ + Milestone = 150; + /*=============================================*/ + printf("Testing powers Z^Q at four nearly extreme values.\n"); + N = 0; + Z = A1; + Q = FLOOR(Half - LOG(C) / LOG(A1)); + Break = False; + do { + X = CInvrse; + Y = POW(Z, Q); + IsYeqX(); + Q = - Q; + X = C; + Y = POW(Z, Q); + IsYeqX(); + if (Z < One) Break = True; + else Z = AInvrse; + } while ( ! (Break)); + PrintIfNPositive(); + if (N == 0) printf(" ... no discrepancies found.\n"); + printf("\n"); + + /*=============================================*/ + Milestone = 160; + /*=============================================*/ + Pause(); + printf("Searching for Overflow threshold:\n"); + printf("This may generate an error.\n"); + Y = - CInvrse; + V9 = HInvrse * Y; + sigsave = sigfpe; + if (setjmp(ovfl_buf)) { I = 0; V9 = Y; goto overflow; } + do { + V = Y; + Y = V9; + V9 = HInvrse * Y; + } while(V9 < Y); + I = 1; +overflow: + sigsave = 0; + Z = V9; + printf("Can `Z = -Y' overflow?\n"); + printf("Trying it on Y = %.17e .\n", Y); + V9 = - Y; + V0 = V9; + if (V - Y == V + V0) printf("Seems O.K.\n"); + else { + printf("finds a "); + BadCond(Flaw, "-(-Y) differs from Y.\n"); + } + if (Z != Y) { + BadCond(Serious, ""); + printf("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z); + } + if (I) { + Y = V * (HInvrse * U2 - HInvrse); + Z = Y + ((One - HInvrse) * U2) * V; + if (Z < V0) Y = Z; + if (Y < V0) V = Y; + if (V0 - V < V0) V = V0; + } + else { + V = Y * (HInvrse * U2 - HInvrse); + V = V + ((One - HInvrse) * U2) * Y; + } + printf("Overflow threshold is V = %.17e .\n", V); + if (I) printf("Overflow saturates at V0 = %.17e .\n", V0); + else printf("There is no saturation value because \ +the system traps on overflow.\n"); + V9 = V * One; + printf("No Overflow should be signaled for V * 1 = %.17e\n", V9); + V9 = V / One; + printf(" nor for V / 1 = %.17e .\n", V9); + printf("Any overflow signal separating this * from the one\n"); + printf("above is a DEFECT.\n"); + /*=============================================*/ + Milestone = 170; + /*=============================================*/ + if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) { + BadCond(Failure, "Comparisons involving "); + printf("+-%g, +-%g\nand +-%g are confused by Overflow.", + V, V0, UfThold); + } + /*=============================================*/ + Milestone = 175; + /*=============================================*/ + printf("\n"); + for(Indx = 1; Indx <= 3; ++Indx) { + switch (Indx) { + case 1: Z = UfThold; break; + case 2: Z = E0; break; + case 3: Z = PseudoZero; break; + } + if (Z != Zero) { + V9 = SQRT(Z); + Y = V9 * V9; + if (Y / (One - Radix * E9) < Z + || Y > (One + Radix * E9) * Z) { /* dgh: + E9 --> * E9 */ + if (V9 > U1) BadCond(Serious, ""); + else BadCond(Defect, ""); + printf("Comparison alleges that what prints as Z = %.17e\n", Z); + printf(" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y); + } + } + } + /*=============================================*/ + Milestone = 180; + /*=============================================*/ + for(Indx = 1; Indx <= 2; ++Indx) { + if (Indx == 1) Z = V; + else Z = V0; + V9 = SQRT(Z); + X = (One - Radix * E9) * V9; + V9 = V9 * X; + if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) { + Y = V9; + if (X < W) BadCond(Serious, ""); + else BadCond(Defect, ""); + printf("Comparison alleges that Z = %17e\n", Z); + printf(" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y); + } + } + /*=============================================*/ + /*SPLIT + } +#include "paranoia.h" +int part8(VOID){ +*/ + Milestone = 190; + /*=============================================*/ + Pause(); + X = UfThold * V; + Y = Radix * Radix; + if (X*Y < One || X > Y) { + if (X * Y < U1 || X > Y/U1) BadCond(Defect, "Badly"); + else BadCond(Flaw, ""); + + printf(" unbalanced range; UfThold * V = %.17e\n\t%s\n", + X, "is too far from 1.\n"); + } + /*=============================================*/ + Milestone = 200; + /*=============================================*/ + for (Indx = 1; Indx <= 5; ++Indx) { + X = F9; + switch (Indx) { + case 2: X = One + U2; break; + case 3: X = V; break; + case 4: X = UfThold; break; + case 5: X = Radix; + } + Y = X; + sigsave = sigfpe; + if (setjmp(ovfl_buf)) + printf(" X / X traps when X = %g\n", X); + else { + V9 = (Y / X - Half) - Half; + if (V9 == Zero) continue; + if (V9 == - U1 && Indx < 5) BadCond(Flaw, ""); + else BadCond(Serious, ""); + printf(" X / X differs from 1 when X = %.17e\n", X); + printf(" instead, X / X - 1/2 - 1/2 = %.17e .\n", V9); + } + sigsave = 0; + } + /*=============================================*/ + Milestone = 210; + /*=============================================*/ + MyZero = Zero; + printf("\n"); + printf("What message and/or values does Division by Zero produce?\n") ; +#ifndef NOPAUSE + printf("This can interupt your program. You can "); + printf("skip this part if you wish.\n"); + printf("Do you wish to compute 1 / 0? "); + fflush(stdout); + read (KEYBOARD, ch, 8); + if ((ch[0] == 'Y') || (ch[0] == 'y')) { +#endif + sigsave = sigfpe; + printf(" Trying to compute 1 / 0 produces ..."); + if (!setjmp(ovfl_buf)) printf(" %.7e .\n", One / MyZero); + sigsave = 0; +#ifndef NOPAUSE + } + else printf("O.K.\n"); + printf("\nDo you wish to compute 0 / 0? "); + fflush(stdout); + read (KEYBOARD, ch, 80); + if ((ch[0] == 'Y') || (ch[0] == 'y')) { +#endif + sigsave = sigfpe; + printf("\n Trying to compute 0 / 0 produces ..."); + if (!setjmp(ovfl_buf)) printf(" %.7e .\n", Zero / MyZero); + sigsave = 0; +#ifndef NOPAUSE + } + else printf("O.K.\n"); +#endif + /*=============================================*/ + Milestone = 220; + /*=============================================*/ + Pause(); + printf("\n"); + { + static char *msg[] = { + "FAILUREs encountered =", + "SERIOUS DEFECTs discovered =", + "DEFECTs discovered =", + "FLAWs discovered =" }; + int i; + for(i = 0; i < 4; i++) if (ErrCnt[i]) + printf("The number of %-29s %d.\n", + msg[i], ErrCnt[i]); + } + printf("\n"); + if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + + ErrCnt[Flaw]) > 0) { + if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[ + Defect] == 0) && (ErrCnt[Flaw] > 0)) { + printf("The arithmetic diagnosed seems "); + printf("Satisfactory though flawed.\n"); + } + if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) + && ( ErrCnt[Defect] > 0)) { + printf("The arithmetic diagnosed may be Acceptable\n"); + printf("despite inconvenient Defects.\n"); + } + if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) { + printf("The arithmetic diagnosed has "); + printf("unacceptable Serious Defects.\n"); + } + if (ErrCnt[Failure] > 0) { + printf("Potentially fatal FAILURE may have spoiled this"); + printf(" program's subsequent diagnoses.\n"); + } + } + else { + printf("No failures, defects nor flaws have been discovered.\n"); + if (! ((RMult == Rounded) && (RDiv == Rounded) + && (RAddSub == Rounded) && (RSqrt == Rounded))) + printf("The arithmetic diagnosed seems Satisfactory.\n"); + else { + if (StickyBit >= One && + (Radix - Two) * (Radix - Nine - One) == Zero) { + printf("Rounding appears to conform to "); + printf("the proposed IEEE standard P"); + if ((Radix == Two) && + ((Precision - Four * Three * Two) * + ( Precision - TwentySeven - + TwentySeven + One) == Zero)) + printf("754"); + else printf("854"); + if (IEEE) printf(".\n"); + else { + printf(",\nexcept for possibly Double Rounding"); + printf(" during Gradual Underflow.\n"); + } + } + printf("The arithmetic diagnosed appears to be Excellent!\n"); + } + } + if (fpecount) + printf("\nA total of %d floating point exceptions were registered.\n", + fpecount); + printf("END OF TEST.\n"); + return 0; + } + +/*SPLIT subs.c +#include "paranoia.h" +*/ + + FLOAT +Sign (FP X) +#ifdef KR_headers +FLOAT X; +#endif +{ return X >= 0. ? 1.0 : -1.0; } + + void +Pause(VOID) +{ +#ifndef NOPAUSE + char ch[8]; + + printf("\nTo continue, press RETURN"); + fflush(stdout); + read(KEYBOARD, ch, 8); +#endif + printf("\nDiagnosis resumes after milestone Number %d", Milestone); + printf(" Page: %d\n\n", PageNo); + ++Milestone; + ++PageNo; + } + + void +TstCond (INT K, INT Valid, CHARP T) +#ifdef KR_headers +int K, Valid; +char *T; +#endif +{ if (! Valid) { BadCond(K,T); printf(".\n"); } } + + void +BadCond(INT K, CHARP T) +#ifdef KR_headers +int K; +char *T; +#endif +{ + static char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" }; + + ErrCnt [K] = ErrCnt [K] + 1; + printf("%s: %s", msg[K], T); + } + + + FLOAT +Random(VOID) +/* Random computes + X = (Random1 + Random9)^5 + Random1 = X - FLOOR(X) + 0.000005 * X; + and returns the new value of Random1 +*/ +{ + FLOAT X, Y; + + X = Random1 + Random9; + Y = X * X; + Y = Y * Y; + X = X * Y; + Y = X - FLOOR(X); + Random1 = Y + X * 0.000005; + return(Random1); + } + + void +SqXMinX (INT ErrKind) +#ifdef KR_headers +int ErrKind; +#endif +{ + FLOAT XA, XB; + + XB = X * BInvrse; + XA = X - XB; + SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp; + if (SqEr != Zero) { + if (SqEr < MinSqEr) MinSqEr = SqEr; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + J = J + 1.0; + BadCond(ErrKind, "\n"); + printf("sqrt( %.17e) - %.17e = %.17e\n", X * X, X, OneUlp * SqEr); + printf("\tinstead of correct value 0 .\n"); + } + } + + void +NewD(VOID) +{ + X = Z1 * Q; + X = FLOOR(Half - X / Radix) * Radix + X; + Q = (Q - X * Z) / Radix + X * X * (D / Radix); + Z = Z - Two * X * D; + if (Z <= Zero) { + Z = - Z; + Z1 = - Z1; + } + D = Radix * D; + } + + void +SR3750(VOID) +{ + if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) { + I = I + 1; + X2 = SQRT(X * D); + Y2 = (X2 - Z2) - (Y - Z2); + X2 = X8 / (Y - Half); + X2 = X2 - Half * X2 * X2; + SqEr = (Y2 + Half) + (Half - X2); + if (SqEr < MinSqEr) MinSqEr = SqEr; + SqEr = Y2 - X2; + if (SqEr > MaxSqEr) MaxSqEr = SqEr; + } + } + + void +IsYeqX(VOID) +{ + if (Y != X) { + if (N <= 0) { + if (Z == Zero && Q <= Zero) + printf("WARNING: computing\n"); + else BadCond(Defect, "computing\n"); + printf("\t(%.17e) ^ (%.17e)\n", Z, Q); + printf("\tyielded %.17e;\n", Y); + printf("\twhich compared unequal to correct %.17e ;\n", + X); + printf("\t\tthey differ by %.17e .\n", Y - X); + } + N = N + 1; /* ... count discrepancies. */ + } + } + + void +SR3980(VOID) +{ + do { + Q = (FLOAT) I; + Y = POW(Z, Q); + IsYeqX(); + if (++I > M) break; + X = Z * X; + } while ( X < W ); + } + + void +PrintIfNPositive(VOID) +{ + if (N > 0) printf("Similar discrepancies have occurred %d times.\n", N); + } + + void +TstPtUf(VOID) +{ + N = 0; + if (Z != Zero) { + printf("Since comparison denies Z = 0, evaluating "); + printf("(Z + Z) / Z should be safe.\n"); + sigsave = sigfpe; + if (setjmp(ovfl_buf)) goto very_serious; + Q9 = (Z + Z) / Z; + printf("What the machine gets for (Z + Z) / Z is %.17e .\n", + Q9); + if (FABS(Q9 - Two) < Radix * U2) { + printf("This is O.K., provided Over/Underflow"); + printf(" has NOT just been signaled.\n"); + } + else { + if ((Q9 < One) || (Q9 > Two)) { +very_serious: + N = 1; + ErrCnt [Serious] = ErrCnt [Serious] + 1; + printf("This is a VERY SERIOUS DEFECT!\n"); + } + else { + N = 1; + ErrCnt [Defect] = ErrCnt [Defect] + 1; + printf("This is a DEFECT!\n"); + } + } + sigsave = 0; + V9 = Z * One; + Random1 = V9; + V9 = One * Z; + Random2 = V9; + V9 = Z / One; + if ((Z == Random1) && (Z == Random2) && (Z == V9)) { + if (N > 0) Pause(); + } + else { + N = 1; + BadCond(Defect, "What prints as Z = "); + printf("%.17e\n\tcompares different from ", Z); + if (Z != Random1) printf("Z * 1 = %.17e ", Random1); + if (! ((Z == Random2) + || (Random2 == Random1))) + printf("1 * Z == %g\n", Random2); + if (! (Z == V9)) printf("Z / 1 = %.17e\n", V9); + if (Random2 != Random1) { + ErrCnt [Defect] = ErrCnt [Defect] + 1; + BadCond(Defect, "Multiplication does not commute!\n"); + printf("\tComparison alleges that 1 * Z = %.17e\n", + Random2); + printf("\tdiffers from Z * 1 = %.17e\n", Random1); + } + Pause(); + } + } + } + + void +notify(CHARP s) +#ifdef KR_headers + char *s; +#endif +{ + printf("%s test appears to be inconsistent...\n", s); + printf(" PLEASE NOTIFY KARPINKSI!\n"); + } + +/*SPLIT msgs.c +#include "paranoia.h" +*/ + + void +msglist(CHARPP s) +#ifdef KR_headers +char **s; +#endif +{ while(*s) printf("%s\n", *s++); } + + void +Instructions(VOID) +{ + static char *instr[] = { + "Lest this program stop prematurely, i.e. before displaying\n", + " `END OF TEST',\n", + "try to persuade the computer NOT to terminate execution when an", + "error like Over/Underflow or Division by Zero occurs, but rather", + "to persevere with a surrogate value after, perhaps, displaying some", + "warning. If persuasion avails naught, don't despair but run this", + "program anyway to see how many milestones it passes, and then", + "amend it to make further progress.\n", + "Answer questions with Y, y, N or n (unless otherwise indicated).\n", + 0}; + + msglist(instr); + } + + void +Heading(VOID) +{ + static char *head[] = { + "Users are invited to help debug and augment this program so it will", + "cope with unanticipated and newly uncovered arithmetic pathologies.\n", + "Please send suggestions and interesting results to", + "\tRichard Karpinski", + "\tComputer Center U-76", + "\tUniversity of California", + "\tSan Francisco, CA 94143-0704, USA\n", + "In doing so, please include the following information:", +#ifdef Single + "\tPrecision:\tsingle;", +#else + "\tPrecision:\tdouble;", +#endif + "\tVersion:\t10 February 1989;", + "\tComputer:\n", + "\tCompiler:\n", + "\tOptimization level:\n", + "\tOther relevant compiler options:", + 0}; + + msglist(head); + } + + void +Characteristics(VOID) +{ + static char *chars[] = { + "Running this program should reveal these characteristics:", + " Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...", + " Precision = number of significant digits carried.", + " U2 = Radix/Radix^Precision = One Ulp", + "\t(OneUlpnit in the Last Place) of 1.000xxx .", + " U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .", + " Adequacy of guard digits for Mult., Div. and Subt.", + " Whether arithmetic is chopped, correctly rounded, or something else", + "\tfor Mult., Div., Add/Subt. and Sqrt.", + " Whether a Sticky Bit used correctly for rounding.", + " UnderflowThreshold = an underflow threshold.", + " E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.", + " V = an overflow threshold, roughly.", + " V0 tells, roughly, whether Infinity is represented.", + " Comparisions are checked for consistency with subtraction", + "\tand for contamination with pseudo-zeros.", + " Sqrt is tested. Y^X is not tested.", + " Extra-precise subexpressions are revealed but NOT YET tested.", + " Decimal-Binary conversion is NOT YET tested for accuracy.", + 0}; + + msglist(chars); + } + + void +History(VOID) +{ /* History */ + /* Converted from Brian Wichmann's Pascal version to C by Thos Sumner, + with further massaging by David M. Gay. */ + + static char *hist[] = { + "The program attempts to discriminate among", + " FLAWs, like lack of a sticky bit,", + " Serious DEFECTs, like lack of a guard digit, and", + " FAILUREs, like 2+2 == 5 .", + "Failures may confound subsequent diagnoses.\n", + "The diagnostic capabilities of this program go beyond an earlier", + "program called `MACHAR', which can be found at the end of the", + "book `Software Manual for the Elementary Functions' (1980) by", + "W. J. Cody and W. Waite. Although both programs try to discover", + "the Radix, Precision and range (over/underflow thresholds)", + "of the arithmetic, this program tries to cope with a wider variety", + "of pathologies, and to say how well the arithmetic is implemented.", + "\nThe program is based upon a conventional radix representation for", + "floating-point numbers, but also allows logarithmic encoding", + "as used by certain early WANG machines.\n", + "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;", + "see source comments for more history.", + 0}; + + msglist(hist); + } diff --git a/src/tests/Simple.c b/src/tests/Simple.c new file mode 100644 index 0000000..bb8452e --- /dev/null +++ b/src/tests/Simple.c @@ -0,0 +1,9 @@ +#include + +char *a = "bar"; + +volatile char buf[] = "Hello World"; + +int _start() { + return strlen("foo"); +} diff --git a/src/tests/SpeedTest.java b/src/tests/SpeedTest.java new file mode 100644 index 0000000..5362961 --- /dev/null +++ b/src/tests/SpeedTest.java @@ -0,0 +1,66 @@ +package tests; + +import org.xwt.mips.Runtime; +import org.xwt.mips.Interpreter; + +class SpeedTest { + private static long start,end; + private static long now() { return System.currentTimeMillis(); } + private static void start() { start = now(); } + private static void end() { end = now(); } + private static float diff() { return ((float)(end-start))/1000; } + + public static void main(String[] args) throws Exception { + float d; + + if(args.length < 2) { System.err.println("Usage: SpeedTest {classname|mips binary} number_of_runs args"); System.exit(1); } + String className = args[0]; + int runs = Integer.parseInt(args[1]); + if(runs < 5) throw new Error("Runs must be >= 5"); + String[] appArgs = new String[args.length-1]; + appArgs[0] = className; + for(int i=2;i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *user_info[1024]; + +extern void _pause(); +extern int _call_java(int a, int b, int c, int d); + +void suckram(); + +int main(int argc, char **argv) { + int i,n,fd; + time_t now; + DIR *dir; + struct dirent *dent; + char buf[1024]; + unsigned char ubuf[1024]; + unsigned short sbuf[1024]; + char *s; + + printf("Entered main()\n"); + + if(argc > 1 && strcmp(argv[1],"calltest")==0) { + printf("pausing for call test\n"); + _pause(); + printf("unpaused from call test\n"); + + for(i=1;i<=3;i++) { + char *s = (char*)_call_java(i,0,0,0); + printf("_call_java(%d,0,0,0) = \"%s\" (%d chars)\n",i,s,strlen(s)); + free(s); + } + fd = _call_java(4,0,0,0); + if(fd != -1) { + FILE *fp; + fprintf(stderr,"fd: %i\n",fd); + fp = fdopen(fd,"w"); + if(fp != NULL) { + fprintf(fp,"It worked! fp is %p - Hello, Java!\n",fp); + fclose(fp); + } else { + fprintf(stderr,"fdopen failed\n"); + close(fd); + } + } else { + fprintf(stderr,"fd == -1\n"); + } + + printf("In main() in MIPS\n"); + _call_java(5,0,0,0); + printf("Back in main() in MIPS\n"); + } else if(argc > 2 && strcmp(argv[1],"fdtest")==0) { + printf("opening %s\n",argv[2]); + fd = open(argv[2],O_RDONLY); + if(fd < 0) { perror("open"); exit(1); } + + printf("reading up to 64 bytes\n"); + n = read(fd,buf,64); + if(n < 0) {perror("read"); exit(1); } + printf("read %d bytes\n",n); + for(i=0;i 1 && strcmp(argv[1],"fptest")==0) { + double d = 0.0; + while(d != 10.0) { + printf("d: %f\n",d); + d += 2.5; + } + } else if(argc > 1 && strcmp(argv[1],"nullderef")==0) { + volatile int *mem = 0; + *mem = 1; + } else { + printf("%d\n", 0xffffff); + printf("%u\n", 0xffffffU); + printf("%li\n",0xffffffL); + printf("%lu\n",0xffffffUL); + + + for(i=0;id_name,dent->d_ino); + closedir(dir); + } else { + perror("opendir"); + } + + +#if 0 + printf("Sleeping...\n"); + sleep(1); + printf("Done\n"); +#endif + + fd = open("test.txt",O_RDONLY); + if(fd != -1) { + printf("Opened test.txt\n"); + n = read(fd,sbuf,sizeof(sbuf)); + printf("n: %d\n",n); + if(n < 0) perror("read"); + ubuf[n] = '\0'; + printf("buf: %s\n",buf); + for(i=0;i&2 + exit 1 +fi + +INT="$2" + +cd tmp + +if [ ! -e .skipmspack ]; then + +mkdir -p mspack +cd mspack +rm -f *.TTT *.inf FONTINST.EXE *.DLL *.TXT; +for f in \ + andale32.exe arial32.exe arialb32.exe comic32.exe courie32.exe georgi32.exe \ + impact32.exe times32.exe trebuc32.exe verdan32.exe webdin32.exe; \ +do + [ -e "$f" ] || wget "http://dist.xwt.org/corefonts/$f" || rm -f "$f" + [ -e "$f" ] || exit 1 +done + +echo "Extracting MS Core Fonts using MSPackBench..." +$JAVA tests.MSPackBench *32.exe + +cat < md5.1" + md5sum mspack/*.ttf > md5.2 + cmp md5.1 md5.2 && echo "The BusyBox md5sum command and sh work properly!" +fi + +cat <' > install/mips-unknown-elf/include/getopt.h + touch $@ + +clean_%: + rm -rf "build/$(*)"* + rm -f "tasks/build_$*" "tasks/patch_$*" "tasks/extract_$*" + +tasks/download_%: + if [ -z "$(url_$*)" ]; then echo "No url for $*" >&2; false; fi + mkdir -p download + cd download && wget --passive-ftp -N $(url_$*) + touch $@ + +tasks/download_gcc: tasks/download_gcc-core tasks/download_gcc-c++ + touch $@ + +tasks/extract_%: tasks/download_% + mkdir -p build + cd build && \ + gzip -dc ../download/$*-$(version_$*).tar.gz | tar xf - && \ + rm -f $* && \ + ln -s $*-$(version_$*) $* + touch $@ + +tasks/extract_gcc: tasks/download_gcc + mkdir -p build + cd build && gzip -dc ../download/gcc-core-$(version_gcc).tar.gz | tar xf - + cd build && gzip -dc ../download/gcc-g++-$(version_gcc).tar.gz | tar xf - + touch $@ + +tasks/patch_%: tasks/extract_% + cd build/$*-$(version_$*) && \ + for p in $(patches_$*) end; do \ + [ "$$p" = "end" ] || $(PATCH) -p0 < ../../patches/$$p || exit 1; \ + done + touch $@ + +tasks/build_%: tasks/patch_% + mkdir -p install + @[ "$*" = "newlib" ] && rm -f install/mips-unknown-elf/lib/crt0.o || true + mkdir -p build/$*-obj && cd build/$*-obj && \ + ../$*-$(version_$*)/configure --prefix=$(prefix) $(configure_$*) && \ + $(MAKE) TARGET_CFLAGS="$(MIPS_CFLAGS)" && \ + $(MAKE) install + touch $@ + +tasks/build_gcc_step2: tasks/patch_gcc tasks/build_libc + mkdir -p install + mkdir -p build/gcc-obj && cd build/gcc-obj && \ + ../gcc-$(version_gcc)/configure --prefix=$(prefix) $(configure_gcc_step2) && \ + $(MAKE) TARGET_CFLAGS="$(MIPS_CFLAGS)" && \ + $(MAKE) install + touch $@ + +tasks/build_openbsdglob: tasks/download_openbsdglob tasks/build_newlib + @mkdir -p install/mips-unknown-elf/{include,lib} + cd build && gzip -dc ../download/openbsdglob.tar.gz | tar xf - + cd build/openbsdglob && \ + mips-unknown-elf-gcc '-Dissetugid()=0' -DARG_MAX=65536 $(MIPS_CFLAGS) -I. -c -o glob.o glob.c && \ + mips-unknown-elf-gcc -O2 -Wall -Werror -I. -c -o fnmatch.o fnmatch.c && \ + mips-unknown-elf-ar cr libglob.a *.o && \ + mips-unknown-elf-ranlib libglob.a && \ + cp *.h ../../install/mips-unknown-elf/include && \ + cp *.a ../../install/mips-unknown-elf/lib + touch $@ + +tasks/build_regex: tasks/download_regex tasks/build_newlib + @mkdir -p install/mips-unknown-elf/{include,lib} + mkdir -p build/regex build/regex/fake + cd build/regex && \ + sh ../../download/regex.shar && \ + make CC=mips-unknown-elf-gcc CFLAGS="-I. $(MIPS_CFLAGS)" regcomp.o regexec.o regerror.o regfree.o && \ + mips-unknown-elf-ar cr libregex.a regcomp.o regexec.o regerror.o regfree.o && \ + mips-unknown-elf-ranlib libregex.a && \ + cp regex.h ../../install/mips-unknown-elf/include && \ + cp libregex.a ../../install/mips-unknown-elf/lib + touch $@ + + +# +# Tests +# These are simply here for convenience. They aren't required +# to build or run mips2java +# + +tasks/build_freetype: tasks/full_toolchain +tasks/build_libjpeg: tasks/full_toolchain +tasks/build_boehmgc: tasks/full_toolchain +tasks/build_libmspack: tasks/full_toolchain +tasks/build_freetype: tasks/full_toolchain + +version_libjpeg = 6b +url_libjpeg = http://www.ijg.org/files/jpegsrc.v$(version_libjpeg).tar.gz + +version_libmspack = 20030726 +url_libmspack = http://www.kyz.uklinux.net/downloads/libmspack-$(version_libmspack).tar.gz +patches_libmspack = libmspack.patch + +version_freetype = 2.1.4 +url_freetype = http://umn.dl.sourceforge.net/sourceforge/freetype/freetype-$(version_freetype).tar.gz +patches_freetype = freetype.patch ft-nostdio.patch + +version_boehmgc = 6.3alpha2 +url_boehmgc = http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc$(version_boehmgc).tar.gz +patches_boehmgc = boehm-gc.patch + +version_busybox = 0.60.5 +url_busybox = http://busybox.net/downloads/busybox-$(version_busybox).tar.gz +patches_busybox = busybox.patch + + +tasks/extract_libjpeg: tasks/download_libjpeg + mkdir -p build + cd build && \ + gzip -dc ../download/jpegsrc.v$(version_libjpeg).tar.gz | tar xf - && \ + mv jpeg-$(version_libjpeg) libjpeg-$(version_libjpeg) && \ + rm -f libjpeg && \ + ln -s libjpeg-$(version_libjpeg) libjpeg + touch $@ + +tasks/build_libjpeg: tasks/patch_libjpeg + cd build/libjpeg-$(version_libjpeg) && \ + ./configure && \ + make CC="mips-unknown-elf-gcc" \ + AR="mips-unknown-elf-ar rc" \ + AR2="mips-unknown-elf-ranlib" \ + CFLAGS="$(MIPS_CFLAGS)" \ + LDFLAGS="$(MIPS_LDFLAGS)" + touch $@ + +tasks/extract_libmspack: tasks/download_libmspack + mkdir -p build + cd build && \ + gzip -dc ../download/libmspack-$(version_libmspack).tar.gz | tar xf - && \ + mv libmspack libmspack-$(version_libmspack) && \ + rm -f libmspack && \ + ln -s libmspack-$(version_libmspack) libmspack + touch $@ + +tasks/build_libmspack: tasks/patch_libmspack tasks/full_toolchain + cd build/libmspack-$(version_libmspack)/mspack && \ + make CC="mips-unknown-elf-gcc" \ + AR="mips-unknown-elf-ar" \ + RANLIB="mips-unknown-elf-ranlib" \ + OPTIM="$(MIPS_CFLAGS)" + touch $@ + +tasks/build_freetype: tasks/patch_freetype tasks/full_toolchain + cd build/freetype-$(version_freetype) && \ + $(MAKE) setup ansi && \ + $(MAKE) CC="mips-unknown-elf-gcc" \ + CFLAGS="-c $(MIPS_CFLAGS)" \ + AR="mips-unknown-elf-ar" \ + RANLIB="mips-unknown-elf-ranlib" && \ + mips-unknown-elf-ranlib objs/libfreetype.a + touch $@ + +tasks/extract_boehmgc: tasks/download_boehmgc + mkdir -p build + cd build && \ + rm -rf gc$(version_boehmgc) && \ + gzip -dc ../download/gc$(version_boehmgc).tar.gz | tar xf - && \ + rm -f boehmgc boehmgc-$(version_boehmgc) && \ + ln -s gc$(version_boehmgc) boehmgc && \ + ln -s gc$(version_boehmgc) boehmgc-$(version_boehmgc) + touch $@ + +tasks/build_boehmgc: tasks/patch_boehmgc tasks/full_toolchain + cd build/gc$(version_boehmgc) && \ + CC="mips-unknown-elf-gcc" CFLAGS="$(MIPS_CFLAGS)" LDFLAGS="$(MIPS_LDFLAGS)" \ + ./configure --host=mips-unknown-elf --disable-shared --disable-threads && \ + make && \ + make gctest + touch $@ + +tasks/build_busybox: tasks/patch_busybox tasks/full_toolchain + cd build && \ + rm -f busybox && \ + ln -s busybox-$(version_busybox) busybox + cd build/busybox && $(MAKE) SHELL=/bin/bash LDFLAGS="$(MIPS_LDFLAGS)" CFLAGS_EXTRA="$(MIPS_CFLAGS) -g" + touch $@ diff --git a/upstream/patches/binutils-no64.patch b/upstream/patches/binutils-no64.patch new file mode 100644 index 0000000..ca684f9 --- /dev/null +++ b/upstream/patches/binutils-no64.patch @@ -0,0 +1,29 @@ +diff -ru ../binutils-2.14/bfd/config.bfd ./bfd/config.bfd +--- ../binutils-2.14/bfd/config.bfd Mon Jun 2 16:35:20 2003 ++++ ./bfd/config.bfd Mon Sep 1 01:06:32 2003 +@@ -777,6 +777,10 @@ + targ_defvec=bfd_elf32_littlemips_vec + targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec" + ;; ++ mips*-unknown-elf*) ++ targ_defvec=bfd_elf32_bigmips_vec ++ targ_selvecs=bfd_elf32_littlemips_vec ++ ;; + mips*-*-elf* | mips*-*-rtems* | mips*-*-vxworks*) + targ_defvec=bfd_elf32_bigmips_vec + targ_selvecs="bfd_elf32_littlemips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec" +Only in ./bfd: config.bfd.old +Only in ./bfd: config.bfd~ +diff -ru ../binutils-2.14/ld/configure.tgt ./ld/configure.tgt +--- ../binutils-2.14/ld/configure.tgt Thu Jun 12 10:25:52 2003 ++++ ./ld/configure.tgt Mon Sep 1 01:07:42 2003 +@@ -405,6 +405,7 @@ + mips*vr5000el-*-elf*) targ_emul=elf32l4300 ;; + mips*vr5000-*-elf*) targ_emul=elf32b4300 ;; + mips*el-*-elf*) targ_emul=elf32elmip ;; ++mips*-unknown-elf*) targ_emul=elf32ebmip ;; + mips*-*-elf*) targ_emul=elf32ebmip ;; + mips*el-*-rtems*) targ_emul=elf32elmip ;; + mips*-*-rtems*) targ_emul=elf32ebmip ;; +Only in ./ld: configure.tgt.old +Only in ./ld: configure.tgt~ diff --git a/upstream/patches/boehm-gc.patch b/upstream/patches/boehm-gc.patch new file mode 100644 index 0000000..48103d3 --- /dev/null +++ b/upstream/patches/boehm-gc.patch @@ -0,0 +1,2879 @@ +diff -ruN ../gc6.3alpha2/configure ./configure +--- ../gc6.3alpha2/configure Wed Oct 1 19:34:32 2003 ++++ ./configure Wed Nov 19 04:17:25 2003 +@@ -1,7 +1,7 @@ + #! /bin/sh + # From configure.in Revision: 1.2 . + # Guess values for system-dependent variables and create Makefiles. +-# Generated by GNU Autoconf 2.53 for gc 6.3alpha2. ++# Generated by GNU Autoconf 2.57 for gc 6.3alpha2. + # + # Report bugs to . + # +@@ -9,173 +9,6 @@ + # Free Software Foundation, Inc. + # This configure script is free software; the Free Software Foundation + # gives unlimited permission to copy, distribute and modify it. +- +-# Find the correct PATH separator. Usually this is `:', but +-# DJGPP uses `;' like DOS. +-if test "X${PATH_SEPARATOR+set}" != Xset; then +- UNAME=${UNAME-`uname 2>/dev/null`} +- case X$UNAME in +- *-DOS) lt_cv_sys_path_separator=';' ;; +- *) lt_cv_sys_path_separator=':' ;; +- esac +- PATH_SEPARATOR=$lt_cv_sys_path_separator +-fi +- +- +-# Check that we are running under the correct shell. +-SHELL=${CONFIG_SHELL-/bin/sh} +- +-case X$ECHO in +-X*--fallback-echo) +- # Remove one level of quotation (which was required for Make). +- ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` +- ;; +-esac +- +-echo=${ECHO-echo} +-if test "X$1" = X--no-reexec; then +- # Discard the --no-reexec flag, and continue. +- shift +-elif test "X$1" = X--fallback-echo; then +- # Avoid inline document here, it may be left over +- : +-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then +- # Yippee, $echo works! +- : +-else +- # Restart under the correct shell. +- exec $SHELL "$0" --no-reexec ${1+"$@"} +-fi +- +-if test "X$1" = X--fallback-echo; then +- # used as fallback echo +- shift +- cat </dev/null && +- echo_test_string="`eval $cmd`" && +- (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null +- then +- break +- fi +- done +-fi +- +-if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && +- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- : +-else +- # The Solaris, AIX, and Digital Unix default echo programs unquote +- # backslashes. This makes it impossible to quote backslashes using +- # echo "$something" | sed 's/\\/\\\\/g' +- # +- # So, first we look for a working echo in the user's PATH. +- +- IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR +- for dir in $PATH /usr/ucb; do +- if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && +- test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && +- echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- echo="$dir/echo" +- break +- fi +- done +- IFS="$save_ifs" +- +- if test "X$echo" = Xecho; then +- # We didn't find a better echo, so look for alternatives. +- if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && +- echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- # This shell has a builtin print -r that does the trick. +- echo='print -r' +- elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && +- test "X$CONFIG_SHELL" != X/bin/ksh; then +- # If we have ksh, try running configure again with it. +- ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +- export ORIGINAL_CONFIG_SHELL +- CONFIG_SHELL=/bin/ksh +- export CONFIG_SHELL +- exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} +- else +- # Try using printf. +- echo='printf %s\n' +- if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && +- echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- # Cool, printf works +- : +- elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && +- test "X$echo_testing_string" = 'X\t' && +- echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL +- export CONFIG_SHELL +- SHELL="$CONFIG_SHELL" +- export SHELL +- echo="$CONFIG_SHELL $0 --fallback-echo" +- elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && +- test "X$echo_testing_string" = 'X\t' && +- echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && +- test "X$echo_testing_string" = "X$echo_test_string"; then +- echo="$CONFIG_SHELL $0 --fallback-echo" +- else +- # maybe with a smaller string... +- prev=: +- +- for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do +- if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null +- then +- break +- fi +- prev="$cmd" +- done +- +- if test "$prev" != 'sed 50q "$0"'; then +- echo_test_string=`eval $prev` +- export echo_test_string +- exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} +- else +- # Oops. We lost completely, so just stick with echo. +- echo=echo +- fi +- fi +- fi +- fi +-fi +-fi +- +-# Copy echo and quote the copy suitably for passing to libtool from +-# the Makefile, instead of quoting the original, which is used later. +-ECHO=$echo +-if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then +- ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +-fi +- +- +- +-if expr a : '\(a\)' >/dev/null 2>&1; then +- as_expr=expr +-else +- as_expr=false +-fi +- +- + ## --------------------- ## + ## M4sh Initialization. ## + ## --------------------- ## +@@ -184,11 +17,13 @@ + if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: ++ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which ++ # is contrary to our usage. Disable this feature. ++ alias -g '${1+"$@"}'='"$@"' + elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix + fi + +-# NLS nuisances. + # Support unset when possible. + if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +@@ -196,34 +31,42 @@ + as_unset=false + fi + +-(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && +- { $as_unset LANG || test "${LANG+set}" != set; } || +- { LANG=C; export LANG; } +-(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && +- { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || +- { LC_ALL=C; export LC_ALL; } +-(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && +- { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || +- { LC_TIME=C; export LC_TIME; } +-(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && +- { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || +- { LC_CTYPE=C; export LC_CTYPE; } +-(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && +- { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || +- { LANGUAGE=C; export LANGUAGE; } +-(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && +- { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || +- { LC_COLLATE=C; export LC_COLLATE; } +-(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && +- { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || +- { LC_NUMERIC=C; export LC_NUMERIC; } +-(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && +- { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || +- { LC_MESSAGES=C; export LC_MESSAGES; } ++ ++# Work around bugs in pre-3.0 UWIN ksh. ++$as_unset ENV MAIL MAILPATH ++PS1='$ ' ++PS2='> ' ++PS4='+ ' ++ ++# NLS nuisances. ++for as_var in \ ++ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ ++ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ ++ LC_TELEPHONE LC_TIME ++do ++ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then ++ eval $as_var=C; export $as_var ++ else ++ $as_unset $as_var ++ fi ++done ++ ++# Required to use basename. ++if expr a : '\(a\)' >/dev/null 2>&1; then ++ as_expr=expr ++else ++ as_expr=false ++fi ++ ++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then ++ as_basename=basename ++else ++ as_basename=false ++fi + + + # Name of the executable. +-as_me=`(basename "$0") 2>/dev/null || ++as_me=`$as_basename "$0" || + $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ +@@ -234,6 +77,7 @@ + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ++ + # PATH needs CR, and LINENO needs CR and PATH. + # Avoid depending upon Character Ranges. + as_cr_letters='abcdefghijklmnopqrstuvwxyz' +@@ -244,15 +88,15 @@ + + # The user is always right. + if test "${PATH_SEPARATOR+set}" != set; then +- echo "#! /bin/sh" >conftest.sh +- echo "exit 0" >>conftest.sh +- chmod +x conftest.sh +- if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then ++ echo "#! /bin/sh" >conf$$.sh ++ echo "exit 0" >>conf$$.sh ++ chmod +x conf$$.sh ++ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi +- rm -f conftest.sh ++ rm -f conf$$.sh + fi + + +@@ -300,6 +144,8 @@ + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then ++ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } ++ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} +@@ -372,6 +218,12 @@ + fi + rm -f conf$$ conf$$.exe conf$$.file + ++if mkdir -p . 2>/dev/null; then ++ as_mkdir_p=: ++else ++ as_mkdir_p=false ++fi ++ + as_executable_p="test -f" + + # Sed expression to map a string onto a valid CPP name. +@@ -388,7 +240,166 @@ + IFS=" $as_nl" + + # CDPATH. +-$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } ++$as_unset CDPATH ++ ++ ++# Find the correct PATH separator. Usually this is `:', but ++# DJGPP uses `;' like DOS. ++if test "X${PATH_SEPARATOR+set}" != Xset; then ++ UNAME=${UNAME-`uname 2>/dev/null`} ++ case X$UNAME in ++ *-DOS) lt_cv_sys_path_separator=';' ;; ++ *) lt_cv_sys_path_separator=':' ;; ++ esac ++ PATH_SEPARATOR=$lt_cv_sys_path_separator ++fi ++ ++ ++# Check that we are running under the correct shell. ++SHELL=${CONFIG_SHELL-/bin/sh} ++ ++case X$ECHO in ++X*--fallback-echo) ++ # Remove one level of quotation (which was required for Make). ++ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ++ ;; ++esac ++ ++echo=${ECHO-echo} ++if test "X$1" = X--no-reexec; then ++ # Discard the --no-reexec flag, and continue. ++ shift ++elif test "X$1" = X--fallback-echo; then ++ # Avoid inline document here, it may be left over ++ : ++elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then ++ # Yippee, $echo works! ++ : ++else ++ # Restart under the correct shell. ++ exec $SHELL "$0" --no-reexec ${1+"$@"} ++fi ++ ++if test "X$1" = X--fallback-echo; then ++ # used as fallback echo ++ shift ++ cat </dev/null && ++ echo_test_string="`eval $cmd`" && ++ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null ++ then ++ break ++ fi ++ done ++fi ++ ++if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && ++ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ : ++else ++ # The Solaris, AIX, and Digital Unix default echo programs unquote ++ # backslashes. This makes it impossible to quote backslashes using ++ # echo "$something" | sed 's/\\/\\\\/g' ++ # ++ # So, first we look for a working echo in the user's PATH. ++ ++ IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR ++ for dir in $PATH /usr/ucb; do ++ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && ++ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && ++ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ echo="$dir/echo" ++ break ++ fi ++ done ++ IFS="$save_ifs" ++ ++ if test "X$echo" = Xecho; then ++ # We didn't find a better echo, so look for alternatives. ++ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && ++ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ # This shell has a builtin print -r that does the trick. ++ echo='print -r' ++ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && ++ test "X$CONFIG_SHELL" != X/bin/ksh; then ++ # If we have ksh, try running configure again with it. ++ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} ++ export ORIGINAL_CONFIG_SHELL ++ CONFIG_SHELL=/bin/ksh ++ export CONFIG_SHELL ++ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} ++ else ++ # Try using printf. ++ echo='printf %s\n' ++ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && ++ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ # Cool, printf works ++ : ++ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && ++ test "X$echo_testing_string" = 'X\t' && ++ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL ++ export CONFIG_SHELL ++ SHELL="$CONFIG_SHELL" ++ export SHELL ++ echo="$CONFIG_SHELL $0 --fallback-echo" ++ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && ++ test "X$echo_testing_string" = 'X\t' && ++ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && ++ test "X$echo_testing_string" = "X$echo_test_string"; then ++ echo="$CONFIG_SHELL $0 --fallback-echo" ++ else ++ # maybe with a smaller string... ++ prev=: ++ ++ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do ++ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null ++ then ++ break ++ fi ++ prev="$cmd" ++ done ++ ++ if test "$prev" != 'sed 50q "$0"'; then ++ echo_test_string=`eval $prev` ++ export echo_test_string ++ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} ++ else ++ # Oops. We lost completely, so just stick with echo. ++ echo=echo ++ fi ++ fi ++ fi ++ fi ++fi ++fi ++ ++# Copy echo and quote the copy suitably for passing to libtool from ++# the Makefile, instead of quoting the original, which is used later. ++ECHO=$echo ++if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ++ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" ++fi ++ + + + # Name of the host. +@@ -402,6 +413,7 @@ + # Initializations. + # + ac_default_prefix=/usr/local ++ac_config_libobj_dir=. + cross_compiling=no + subdirs= + MFLAGS= +@@ -458,6 +470,8 @@ + # include + #endif" + ++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE GC_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE CCAS CCASFLAGS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS THREADLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE INCLUDES CXXINCLUDES addobjs addincludes addlibs addtests LN_S ECHO CPP EGREP LIBTOOL MY_CFLAGS USE_LIBDIR_TRUE USE_LIBDIR_FALSE LIBOBJS LTLIBOBJS' ++ac_subst_files='' + + # Initialize some variables set by options. + ac_init_help= +@@ -881,6 +895,9 @@ + { (exit 1); exit 1; }; } + fi + fi ++(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || ++ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 ++ { (exit 1); exit 1; }; } + srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` + ac_env_build_alias_set=${build_alias+set} + ac_env_build_alias_value=$build_alias +@@ -1080,7 +1097,7 @@ + # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be + # absolute. + ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` ++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` + ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` + ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +@@ -1107,7 +1124,7 @@ + if $ac_init_version; then + cat <<\_ACEOF + gc configure 6.3alpha2 +-generated by GNU Autoconf 2.53 ++generated by GNU Autoconf 2.57 + + Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. +@@ -1122,7 +1139,7 @@ + running configure, to aid debugging if configure makes a mistake. + + It was created by gc $as_me 6.3alpha2, which was +-generated by GNU Autoconf 2.53. Invocation command line was ++generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +@@ -1174,27 +1191,54 @@ + + # Keep a trace of the command line. + # Strip out --no-create and --no-recursion so they do not pile up. ++# Strip out --silent because we don't want to record it for future runs. + # Also quote any args containing shell meta-characters. ++# Make two passes to allow for proper duplicate-argument suppression. + ac_configure_args= ++ac_configure_args0= ++ac_configure_args1= + ac_sep= +-for ac_arg ++ac_must_keep_next=false ++for ac_pass in 1 2 + do +- case $ac_arg in +- -no-create | --no-create | --no-creat | --no-crea | --no-cre \ +- | --no-cr | --no-c | -n ) continue ;; +- -no-recursion | --no-recursion | --no-recursio | --no-recursi \ +- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) +- continue ;; +- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) +- ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; +- esac +- case " $ac_configure_args " in +- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. +- *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" +- ac_sep=" " ;; +- esac +- # Get rid of the leading space. ++ for ac_arg ++ do ++ case $ac_arg in ++ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil) ++ continue ;; ++ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ++ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; ++ esac ++ case $ac_pass in ++ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; ++ 2) ++ ac_configure_args1="$ac_configure_args1 '$ac_arg'" ++ if test $ac_must_keep_next = true; then ++ ac_must_keep_next=false # Got value, back to normal. ++ else ++ case $ac_arg in ++ *=* | --config-cache | -C | -disable-* | --disable-* \ ++ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ ++ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ ++ | -with-* | --with-* | -without-* | --without-* | --x) ++ case "$ac_configure_args0 " in ++ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; ++ esac ++ ;; ++ -* ) ac_must_keep_next=true ;; ++ esac ++ fi ++ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" ++ # Get rid of the leading space. ++ ac_sep=" " ++ ;; ++ esac ++ done + done ++$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } ++$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + + # When interrupted or exit'd, cleanup temporary files, and complete + # config.log. We remove comments because anyway the quotes in there +@@ -1205,6 +1249,7 @@ + # Save into config.log some information that might help in debugging. + { + echo ++ + cat <<\_ASBOX + ## ---------------- ## + ## Cache variables. ## +@@ -1227,6 +1272,35 @@ + esac; + } + echo ++ ++ cat <<\_ASBOX ++## ----------------- ## ++## Output variables. ## ++## ----------------- ## ++_ASBOX ++ echo ++ for ac_var in $ac_subst_vars ++ do ++ eval ac_val=$`echo $ac_var` ++ echo "$ac_var='"'"'$ac_val'"'"'" ++ done | sort ++ echo ++ ++ if test -n "$ac_subst_files"; then ++ cat <<\_ASBOX ++## ------------- ## ++## Output files. ## ++## ------------- ## ++_ASBOX ++ echo ++ for ac_var in $ac_subst_files ++ do ++ eval ac_val=$`echo $ac_var` ++ echo "$ac_var='"'"'$ac_val'"'"'" ++ done | sort ++ echo ++ fi ++ + if test -s confdefs.h; then + cat <<\_ASBOX + ## ----------- ## +@@ -1234,7 +1308,7 @@ + ## ----------- ## + _ASBOX + echo +- sed "/^$/d" confdefs.h ++ sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && +@@ -1399,6 +1473,7 @@ + + + ++ + ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)? + + ac_aux_dir= +@@ -1743,15 +1818,15 @@ + test -n "$AWK" && break + done + +-echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +-echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 ++echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 ++echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 + set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` + if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + cat >conftest.make <<\_ACEOF + all: +- @echo 'ac_maketemp="${MAKE}"' ++ @echo 'ac_maketemp="$(MAKE)"' + _ACEOF + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +@@ -2116,9 +2191,7 @@ + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift +- set dummy "$as_dir/$ac_word" ${1+"$@"} +- shift +- ac_cv_prog_CC="$@" ++ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi + fi + fi +@@ -2223,8 +2296,10 @@ + fi + + +-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 +-echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} ++test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH ++See \`config.log' for more details." >&5 ++echo "$as_me: error: no acceptable C compiler found in \$PATH ++See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + + # Provide some information about the compiler. +@@ -2249,14 +2324,12 @@ + + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2266,7 +2339,7 @@ + } + _ACEOF + ac_clean_files_save=$ac_clean_files +-ac_clean_files="$ac_clean_files a.out a.exe" ++ac_clean_files="$ac_clean_files a.out a.exe b.out" + # Try to create an executable without -o first, disregard a.out. + # It will help us diagnose broken compilers, and finding out an intuition + # of exeext. +@@ -2285,26 +2358,39 @@ + # Be careful to initialize this variable, since it used to be cached. + # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. + ac_cv_exeext= +-for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; +- ls a.out conftest 2>/dev/null; +- ls a.* conftest.* 2>/dev/null`; do ++# b.out is created by i960 compilers. ++for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out ++do ++ test -f "$ac_file" || continue + case $ac_file in +- *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;; +- a.out ) # We found the default executable, but exeext='' is most +- # certainly right. +- break;; +- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` +- # FIXME: I believe we export ac_cv_exeext for Libtool --akim. +- export ac_cv_exeext +- break;; +- * ) break;; ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ++ ;; ++ conftest.$ac_ext ) ++ # This is the source file. ++ ;; ++ [ab].out ) ++ # We found the default executable, but exeext='' is most ++ # certainly right. ++ break;; ++ *.* ) ++ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` ++ # FIXME: I believe we export ac_cv_exeext for Libtool, ++ # but it would be cool to find out if it's true. Does anybody ++ # maintain Libtool? --akim. ++ export ac_cv_exeext ++ break;; ++ * ) ++ break;; + esac + done + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 +-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 +-echo "$as_me: error: C compiler cannot create executables" >&2;} ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++{ { echo "$as_me:$LINENO: error: C compiler cannot create executables ++See \`config.log' for more details." >&5 ++echo "$as_me: error: C compiler cannot create executables ++See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } + fi + +@@ -2331,9 +2417,11 @@ + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +-If you meant to cross compile, use \`--host'." >&5 ++If you meant to cross compile, use \`--host'. ++See \`config.log' for more details." >&5 + echo "$as_me: error: cannot run C compiled programs. +-If you meant to cross compile, use \`--host'." >&2;} ++If you meant to cross compile, use \`--host'. ++See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +@@ -2341,7 +2429,7 @@ + echo "$as_me:$LINENO: result: yes" >&5 + echo "${ECHO_T}yes" >&6 + +-rm -f a.out a.exe conftest$ac_cv_exeext ++rm -f a.out a.exe conftest$ac_cv_exeext b.out + ac_clean_files=$ac_clean_files_save + # Check the compiler produces executables we can run. If not, either + # the compiler is broken, or we cross compile. +@@ -2361,9 +2449,10 @@ + # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will + # work properly (i.e., refer to `conftest.exe'), while it won't with + # `rm'. +-for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do ++for ac_file in conftest.exe conftest conftest.*; do ++ test -f "$ac_file" || continue + case $ac_file in +- *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;; ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; +@@ -2371,8 +2460,10 @@ + esac + done + else +- { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 +-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} ++ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link ++See \`config.log' for more details." >&5 ++echo "$as_me: error: cannot compute suffix of executables: cannot compile and link ++See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + +@@ -2390,14 +2481,12 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2414,16 +2503,19 @@ + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in +- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;; ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac + done + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 +-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 +-echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile ++See \`config.log' for more details." >&5 ++echo "$as_me: error: cannot compute suffix of object files: cannot compile ++See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + +@@ -2440,14 +2532,12 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2474,7 +2564,8 @@ + ac_compiler_gnu=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_compiler_gnu=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -2494,14 +2585,12 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2525,7 +2614,8 @@ + ac_cv_prog_cc_g=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_prog_cc_g=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -2547,6 +2637,102 @@ + CFLAGS= + fi + fi ++echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 ++echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 ++if test "${ac_cv_prog_cc_stdc+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ ac_cv_prog_cc_stdc=no ++ac_save_CC=$CC ++cat >conftest.$ac_ext <<_ACEOF ++#line $LINENO "configure" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++#include ++#include ++#include ++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ ++struct buf { int x; }; ++FILE * (*rcsopen) (struct buf *, struct stat *, int); ++static char *e (p, i) ++ char **p; ++ int i; ++{ ++ return p[i]; ++} ++static char *f (char * (*g) (char **, int), char **p, ...) ++{ ++ char *s; ++ va_list v; ++ va_start (v,p); ++ s = g (p, va_arg (v,int)); ++ va_end (v); ++ return s; ++} ++int test (int i, double x); ++struct s1 {int (*f) (int a);}; ++struct s2 {int (*f) (double a);}; ++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); ++int argc; ++char **argv; ++int ++main () ++{ ++return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ++ ; ++ return 0; ++} ++_ACEOF ++# Don't try gcc -ansi; that turns off useful extensions and ++# breaks some systems' header files. ++# AIX -qlanglvl=ansi ++# Ultrix and OSF/1 -std1 ++# HP-UX 10.20 and later -Ae ++# HP-UX older versions -Aa -D_HPUX_SOURCE ++# SVR4 -Xc -D__EXTENSIONS__ ++for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" ++do ++ CC="$ac_save_CC $ac_arg" ++ rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then ++ ac_cv_prog_cc_stdc=$ac_arg ++break ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++fi ++rm -f conftest.$ac_objext ++done ++rm -f conftest.$ac_ext conftest.$ac_objext ++CC=$ac_save_CC ++ ++fi ++ ++case "x$ac_cv_prog_cc_stdc" in ++ x|xno) ++ echo "$as_me:$LINENO: result: none needed" >&5 ++echo "${ECHO_T}none needed" >&6 ;; ++ *) ++ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 ++echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 ++ CC="$CC $ac_cv_prog_cc_stdc" ;; ++esac ++ + # Some people use a C++ compiler to compile C. Since we use `exit', + # in C++ we need to declare it. In case someone uses the same compiler + # for both compiling C and C++ we need to have the C++ compiler decide +@@ -2579,15 +2765,13 @@ + do + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + $ac_declaration +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2611,20 +2795,19 @@ + : + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + continue + fi + rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + $ac_declaration +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2648,7 +2831,8 @@ + break + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest.$ac_ext + done +@@ -2661,7 +2845,8 @@ + + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest.$ac_ext + ac_ext=c +@@ -2680,7 +2865,7 @@ + rmdir .deps 2>/dev/null + + +-ac_config_commands="$ac_config_commands depfiles" ++ ac_config_commands="$ac_config_commands depfiles" + + + am_make=${MAKE-make} +@@ -2932,14 +3117,12 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -2966,7 +3149,8 @@ + ac_compiler_gnu=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_compiler_gnu=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -2986,14 +3170,12 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -3017,7 +3199,8 @@ + ac_cv_prog_cxx_g=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_prog_cxx_g=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -3050,15 +3233,13 @@ + do + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + $ac_declaration +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -3082,20 +3263,19 @@ + : + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + continue + fi + rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + $ac_declaration +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -3119,7 +3299,8 @@ + break + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest.$ac_ext + done +@@ -3751,7 +3932,11 @@ + LIBS="-ldl $LIBS" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus +@@ -3760,12 +3945,6 @@ + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char dlopen (); +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -3789,7 +3968,8 @@ + ac_cv_lib_dl_dlopen=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_lib_dl_dlopen=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -3936,6 +4116,13 @@ + ;; + mips*-*-linux*) + ;; ++ mips-unknown-elf*) ++ machdep="mips2java_mach_dep.lo" ++ cat >>confdefs.h <<\_ACEOF ++#define MIPS2JAVA 1 ++_ACEOF ++ ++ ;; + mips-*-*) + machdep="mips_sgi_mach_dep.lo" + cat >>confdefs.h <<\_ACEOF +@@ -4595,18 +4782,28 @@ + do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. ++ # Prefer to if __STDC__ is defined, since ++ # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" +-#include ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#ifdef __STDC__ ++# include ++#else ++# include ++#endif + Syntax error + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -4623,7 +4820,8 @@ + : + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + # Broken: fails on valid input. + continue + fi +@@ -4633,13 +4831,17 @@ + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -4657,7 +4859,8 @@ + continue + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + # Passes both tests. + ac_preproc_ok=: + break +@@ -4686,18 +4889,28 @@ + do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. ++ # Prefer to if __STDC__ is defined, since ++ # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" +-#include ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#ifdef __STDC__ ++# include ++#else ++# include ++#endif + Syntax error + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -4714,7 +4927,8 @@ + : + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + # Broken: fails on valid input. + continue + fi +@@ -4724,13 +4938,17 @@ + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -4748,7 +4966,8 @@ + continue + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + # Passes both tests. + ac_preproc_ok=: + break +@@ -4761,8 +4980,10 @@ + if $ac_preproc_ok; then + : + else +- { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 +-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} ++ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check ++See \`config.log' for more details." >&5 ++echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check ++See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + +@@ -4773,6 +4994,21 @@ + ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ++echo "$as_me:$LINENO: checking for egrep" >&5 ++echo $ECHO_N "checking for egrep... $ECHO_C" >&6 ++if test "${ac_cv_prog_egrep+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ if echo a | (grep -E '(a|b)') >/dev/null 2>&1 ++ then ac_cv_prog_egrep='grep -E' ++ else ac_cv_prog_egrep='egrep' ++ fi ++fi ++echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 ++echo "${ECHO_T}$ac_cv_prog_egrep" >&6 ++ EGREP=$ac_cv_prog_egrep ++ ++ + echo "$as_me:$LINENO: checking for ANSI C header files" >&5 + echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 + if test "${ac_cv_header_stdc+set}" = set; then +@@ -4780,48 +5016,59 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + #include + #include + #include + ++int ++main () ++{ ++ ++ ; ++ return 0; ++} + _ACEOF +-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 +- (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ++rm -f conftest.$ac_objext ++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ++ (eval $ac_compile) 2>&5 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err +- rm -f conftest.er1 +- cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +- (exit $ac_status); } >/dev/null; then +- if test -s conftest.err; then +- ac_cpp_err=$ac_c_preproc_warn_flag +- else +- ac_cpp_err= +- fi +-else +- ac_cpp_err=yes +-fi +-if test -z "$ac_cpp_err"; then ++ (exit $ac_status); } && ++ { ac_try='test -s conftest.$ac_objext' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; }; then + ac_cv_header_stdc=yes + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 +- ac_cv_header_stdc=no ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ac_cv_header_stdc=no + fi +-rm -f conftest.err conftest.$ac_ext ++rm -f conftest.$ac_objext conftest.$ac_ext + + if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- egrep "memchr" >/dev/null 2>&1; then ++ $EGREP "memchr" >/dev/null 2>&1; then + : + else + ac_cv_header_stdc=no +@@ -4834,12 +5081,16 @@ + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + + _ACEOF + if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | +- egrep "free" >/dev/null 2>&1; then ++ $EGREP "free" >/dev/null 2>&1; then + : + else + ac_cv_header_stdc=no +@@ -4855,13 +5106,18 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + #if ((' ' & 0x0FF) == 0x020) + # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') + # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) + #else +-# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ ++# define ISLOWER(c) \ ++ (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) + # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +@@ -4894,11 +5150,12 @@ + else + echo "$as_me: program exited with status $ac_status" >&5 + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ( exit $ac_status ) + ac_cv_header_stdc=no + fi +-rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext ++rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext + fi + fi + fi +@@ -4933,7 +5190,11 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + $ac_includes_default + + #include <$ac_header> +@@ -4953,7 +5214,8 @@ + eval "$as_ac_Header=yes" + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + eval "$as_ac_Header=no" + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -4988,7 +5250,11 @@ + echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + $ac_includes_default + #include <$ac_header> + _ACEOF +@@ -5007,7 +5273,8 @@ + ac_header_compiler=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_header_compiler=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -5019,13 +5286,17 @@ + echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include <$ac_header> + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -5042,7 +5313,8 @@ + ac_header_preproc=yes + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_header_preproc=no + fi + rm -f conftest.err conftest.$ac_ext +@@ -5055,14 +5327,32 @@ + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 + echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; ++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ++ ( ++ cat <<\_ASBOX ++## ------------------------------------ ## ++## Report this to bug-autoconf@gnu.org. ## ++## ------------------------------------ ## ++_ASBOX ++ ) | ++ sed "s/^/$as_me: WARNING: /" >&2 ++ ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 + echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 + echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; ++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} ++ ( ++ cat <<\_ASBOX ++## ------------------------------------ ## ++## Report this to bug-autoconf@gnu.org. ## ++## ------------------------------------ ## ++_ASBOX ++ ) | ++ sed "s/^/$as_me: WARNING: /" >&2 ++ ;; + esac + echo "$as_me:$LINENO: checking for $ac_header" >&5 + echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +@@ -5403,7 +5693,7 @@ + case $host in + *-*-irix6*) + # Find out which ABI we are using. +- echo '#line 5406 "configure"' > conftest.$ac_ext ++ echo '#line 5696 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? +@@ -5443,14 +5733,12 @@ + + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -5474,7 +5762,8 @@ + lt_cv_cc_needs_belf=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + lt_cv_cc_needs_belf=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -5777,14 +6066,12 @@ + CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -5823,7 +6110,8 @@ + + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + lt_cv_prog_cc_pic_works=no + + fi +@@ -5866,14 +6154,12 @@ + LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -5897,7 +6183,8 @@ + lt_cv_prog_cc_static_works=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +@@ -5939,7 +6226,7 @@ + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" + compiler_c_o=no +-if { (eval echo configure:5942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then ++if { (eval echo configure:6229: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then +@@ -5981,14 +6268,12 @@ + ac_objext=lo + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -6019,7 +6304,8 @@ + + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest.$ac_ext + ac_objext="$save_objext" +@@ -6067,14 +6353,12 @@ + compiler_rtti_exceptions=no + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -6105,7 +6389,8 @@ + + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + fi + rm -f conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" +@@ -7326,37 +7611,44 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + /* System header to define __stub macros and hopefully few prototypes, +- which can conflict with char shl_load (); below. */ +-#include ++ which can conflict with char shl_load (); below. ++ Prefer to if __STDC__ is defined, since ++ exists even on freestanding compilers. */ ++#ifdef __STDC__ ++# include ++#else ++# include ++#endif + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus + extern "C" ++{ + #endif + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char shl_load (); +-char (*f) (); +- +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif +-int +-main () +-{ + /* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ + #if defined (__stub_shl_load) || defined (__stub___shl_load) + choke me + #else +-f = shl_load; ++char (*f) () = shl_load; ++#endif ++#ifdef __cplusplus ++} + #endif + ++int ++main () ++{ ++return f != shl_load; + ; + return 0; + } +@@ -7376,7 +7668,8 @@ + ac_cv_func_shl_load=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_func_shl_load=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7395,7 +7688,11 @@ + LIBS="-ldld $LIBS" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus +@@ -7404,12 +7701,6 @@ + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char shl_load (); +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -7433,7 +7724,8 @@ + ac_cv_lib_dld_shl_load=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_lib_dld_shl_load=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7451,37 +7743,44 @@ + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + /* System header to define __stub macros and hopefully few prototypes, +- which can conflict with char dlopen (); below. */ +-#include ++ which can conflict with char dlopen (); below. ++ Prefer to if __STDC__ is defined, since ++ exists even on freestanding compilers. */ ++#ifdef __STDC__ ++# include ++#else ++# include ++#endif + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus + extern "C" ++{ + #endif + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char dlopen (); +-char (*f) (); +- +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif +-int +-main () +-{ + /* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ + #if defined (__stub_dlopen) || defined (__stub___dlopen) + choke me + #else +-f = dlopen; ++char (*f) () = dlopen; ++#endif ++#ifdef __cplusplus ++} + #endif + ++int ++main () ++{ ++return f != dlopen; + ; + return 0; + } +@@ -7501,7 +7800,8 @@ + ac_cv_func_dlopen=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_func_dlopen=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7520,7 +7820,11 @@ + LIBS="-ldl $LIBS" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus +@@ -7529,12 +7833,6 @@ + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char dlopen (); +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -7558,7 +7856,8 @@ + ac_cv_lib_dl_dlopen=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_lib_dl_dlopen=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7578,7 +7877,11 @@ + LIBS="-lsvld $LIBS" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus +@@ -7587,12 +7890,6 @@ + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char dlopen (); +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -7616,7 +7913,8 @@ + ac_cv_lib_svld_dlopen=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_lib_svld_dlopen=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7636,7 +7934,11 @@ + LIBS="-ldld $LIBS" + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + + /* Override any gcc2 internal prototype to avoid an error. */ + #ifdef __cplusplus +@@ -7645,12 +7947,6 @@ + /* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ + char dld_link (); +-#ifdef F77_DUMMY_MAIN +-# ifdef __cplusplus +- extern "C" +-# endif +- int F77_DUMMY_MAIN() { return 1; } +-#endif + int + main () + { +@@ -7674,7 +7970,8 @@ + ac_cv_lib_dld_dld_link=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_cv_lib_dld_dld_link=no + fi + rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +@@ -7732,7 +8029,7 @@ + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < conftest.$ac_ext <&6 + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + $ac_includes_default + #include + _ACEOF +@@ -8594,7 +8895,8 @@ + ac_header_compiler=yes + else + echo "$as_me: failed program was:" >&5 +-cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_header_compiler=no + fi + rm -f conftest.$ac_objext conftest.$ac_ext +@@ -8606,13 +8908,17 @@ + echo $ECHO_N "checking sys/dg_sys_info.h presence... $ECHO_C" >&6 + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" +-#include "confdefs.h" ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ + #include + _ACEOF + if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? +- egrep -v '^ *\+' conftest.er1 >conftest.err ++ grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 +@@ -8629,7 +8935,8 @@ + ac_header_preproc=yes + else + echo "$as_me: failed program was:" >&5 +- cat conftest.$ac_ext >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ + ac_header_preproc=no + fi + rm -f conftest.err conftest.$ac_ext +@@ -8642,14 +8949,32 @@ + { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&5 + echo "$as_me: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5 +-echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;};; ++echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;} ++ ( ++ cat <<\_ASBOX ++## ------------------------------------ ## ++## Report this to bug-autoconf@gnu.org. ## ++## ------------------------------------ ## ++_ASBOX ++ ) | ++ sed "s/^/$as_me: WARNING: /" >&2 ++ ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&5 + echo "$as_me: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&5 + echo "$as_me: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5 +-echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;};; ++echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;} ++ ( ++ cat <<\_ASBOX ++## ------------------------------------ ## ++## Report this to bug-autoconf@gnu.org. ## ++## ------------------------------------ ## ++_ASBOX ++ ) | ++ sed "s/^/$as_me: WARNING: /" >&2 ++ ;; + esac + echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5 + echo $ECHO_N "checking for sys/dg_sys_info.h... $ECHO_C" >&6 +@@ -8880,8 +9205,8 @@ + fi + + +-ac_config_files="$ac_config_files Makefile doc/Makefile include/Makefile" +-ac_config_commands="$ac_config_commands default" ++ ac_config_files="$ac_config_files Makefile doc/Makefile include/Makefile" ++ ac_config_commands="$ac_config_commands default" + cat >confcache <<\_ACEOF + # This file is a shell script that caches the results of configure + # tests run on this system so they can be shared between configure +@@ -8892,7 +9217,7 @@ + # config.status only pays attention to the cache file if you give it + # the --recheck option to rerun configure. + # +-# `ac_cv_env_foo' variables (set or unset) will be overriden when ++# `ac_cv_env_foo' variables (set or unset) will be overridden when + # loading this file, other *unset* `ac_cv_foo' will be assigned the + # following values. + +@@ -8927,7 +9252,7 @@ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +-if cmp -s $cache_file confcache; then :; else ++if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file +@@ -8989,6 +9314,21 @@ + rm -f confdef2opt.sed + + ++ac_libobjs= ++ac_ltlibobjs= ++for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue ++ # 1. Remove the extension, and $U if already installed. ++ ac_i=`echo "$ac_i" | ++ sed 's/\$U\././;s/\.o$//;s/\.obj$//'` ++ # 2. Add them. ++ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ++ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' ++done ++LIBOBJS=$ac_libobjs ++ ++LTLIBOBJS=$ac_ltlibobjs ++ ++ + if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. + Usually this means the macro was only invoked conditionally." >&5 +@@ -9038,11 +9378,12 @@ + # configure, is in config.log if it exists. + + debug=false ++ac_cs_recheck=false ++ac_cs_silent=false + SHELL=\${CONFIG_SHELL-$SHELL} + _ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF +- + ## --------------------- ## + ## M4sh Initialization. ## + ## --------------------- ## +@@ -9051,11 +9392,13 @@ + if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: ++ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which ++ # is contrary to our usage. Disable this feature. ++ alias -g '${1+"$@"}'='"$@"' + elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix + fi + +-# NLS nuisances. + # Support unset when possible. + if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +@@ -9063,34 +9406,42 @@ + as_unset=false + fi + +-(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && +- { $as_unset LANG || test "${LANG+set}" != set; } || +- { LANG=C; export LANG; } +-(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && +- { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || +- { LC_ALL=C; export LC_ALL; } +-(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && +- { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || +- { LC_TIME=C; export LC_TIME; } +-(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && +- { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || +- { LC_CTYPE=C; export LC_CTYPE; } +-(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && +- { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || +- { LANGUAGE=C; export LANGUAGE; } +-(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && +- { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || +- { LC_COLLATE=C; export LC_COLLATE; } +-(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && +- { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || +- { LC_NUMERIC=C; export LC_NUMERIC; } +-(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && +- { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || +- { LC_MESSAGES=C; export LC_MESSAGES; } ++ ++# Work around bugs in pre-3.0 UWIN ksh. ++$as_unset ENV MAIL MAILPATH ++PS1='$ ' ++PS2='> ' ++PS4='+ ' ++ ++# NLS nuisances. ++for as_var in \ ++ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ ++ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ ++ LC_TELEPHONE LC_TIME ++do ++ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then ++ eval $as_var=C; export $as_var ++ else ++ $as_unset $as_var ++ fi ++done ++ ++# Required to use basename. ++if expr a : '\(a\)' >/dev/null 2>&1; then ++ as_expr=expr ++else ++ as_expr=false ++fi ++ ++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then ++ as_basename=basename ++else ++ as_basename=false ++fi + + + # Name of the executable. +-as_me=`(basename "$0") 2>/dev/null || ++as_me=`$as_basename "$0" || + $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ +@@ -9101,6 +9452,7 @@ + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ++ + # PATH needs CR, and LINENO needs CR and PATH. + # Avoid depending upon Character Ranges. + as_cr_letters='abcdefghijklmnopqrstuvwxyz' +@@ -9111,15 +9463,15 @@ + + # The user is always right. + if test "${PATH_SEPARATOR+set}" != set; then +- echo "#! /bin/sh" >conftest.sh +- echo "exit 0" >>conftest.sh +- chmod +x conftest.sh +- if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then ++ echo "#! /bin/sh" >conf$$.sh ++ echo "exit 0" >>conf$$.sh ++ chmod +x conf$$.sh ++ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi +- rm -f conftest.sh ++ rm -f conf$$.sh + fi + + +@@ -9168,6 +9520,8 @@ + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then ++ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } ++ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} +@@ -9241,6 +9595,12 @@ + fi + rm -f conf$$ conf$$.exe conf$$.file + ++if mkdir -p . 2>/dev/null; then ++ as_mkdir_p=: ++else ++ as_mkdir_p=false ++fi ++ + as_executable_p="test -f" + + # Sed expression to map a string onto a valid CPP name. +@@ -9257,7 +9617,7 @@ + IFS=" $as_nl" + + # CDPATH. +-$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } ++$as_unset CDPATH + + exec 6>&1 + +@@ -9274,7 +9634,7 @@ + cat >&5 <<_CSEOF + + This file was extended by gc $as_me 6.3alpha2, which was +-generated by GNU Autoconf 2.53. Invocation command line was ++generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS +@@ -9314,6 +9674,7 @@ + + -h, --help print this help, then exit + -V, --version print version number, then exit ++ -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] +@@ -9331,7 +9692,7 @@ + cat >>$CONFIG_STATUS <<_ACEOF + ac_cs_version="\\ + gc config.status 6.3alpha2 +-configured by $0, generated by GNU Autoconf 2.53, ++configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + + Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +@@ -9352,25 +9713,25 @@ + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` +- shift +- set dummy "$ac_option" "$ac_optarg" ${1+"$@"} +- shift ++ ac_shift=: ++ ;; ++ -*) ++ ac_option=$1 ++ ac_optarg=$2 ++ ac_shift=shift + ;; +- -*);; + *) # This is not an option, so the user has probably given explicit + # arguments. ++ ac_option=$1 + ac_need_defaults=false;; + esac + +- case $1 in ++ case $ac_option in + # Handling of the options. + _ACEOF +-cat >>$CONFIG_STATUS <<_ACEOF +- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) +- echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" +- exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; +-_ACEOF + cat >>$CONFIG_STATUS <<\_ACEOF ++ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ++ ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) +@@ -9385,13 +9746,16 @@ + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) +- shift +- CONFIG_FILES="$CONFIG_FILES $1" ++ $ac_shift ++ CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) +- shift +- CONFIG_HEADERS="$CONFIG_HEADERS $1" ++ $ac_shift ++ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil | --si | --s) ++ ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +@@ -9406,6 +9770,20 @@ + shift + done + ++ac_configure_extra_args= ++ ++if $ac_cs_silent; then ++ exec 6>/dev/null ++ ac_configure_extra_args="$ac_configure_extra_args --silent" ++fi ++ ++_ACEOF ++cat >>$CONFIG_STATUS <<_ACEOF ++if \$ac_cs_recheck; then ++ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 ++ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion ++fi ++ + _ACEOF + + cat >>$CONFIG_STATUS <<_ACEOF +@@ -9450,6 +9828,9 @@ + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands + fi + ++# Have a temporary directory for convenience. Make it in the build tree ++# simply because there is no reason to put it here, and in addition, ++# creating and moving files from /tmp can sometimes cause problems. + # Create a temporary directory, and hook for its removal unless debugging. + $debug || + { +@@ -9458,17 +9839,17 @@ + } + + # Create a (secure) tmp directory for tmp files. +-: ${TMPDIR=/tmp} ++ + { +- tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && ++ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" + } || + { +- tmp=$TMPDIR/cs$$-$RANDOM ++ tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) + } || + { +- echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ++ echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } + } + +@@ -9590,10 +9971,13 @@ + s,@LN_S@,$LN_S,;t t + s,@ECHO@,$ECHO,;t t + s,@CPP@,$CPP,;t t ++s,@EGREP@,$EGREP,;t t + s,@LIBTOOL@,$LIBTOOL,;t t + s,@MY_CFLAGS@,$MY_CFLAGS,;t t + s,@USE_LIBDIR_TRUE@,$USE_LIBDIR_TRUE,;t t + s,@USE_LIBDIR_FALSE@,$USE_LIBDIR_FALSE,;t t ++s,@LIBOBJS@,$LIBOBJS,;t t ++s,@LTLIBOBJS@,$LTLIBOBJS,;t t + CEOF + + _ACEOF +@@ -9664,25 +10048,30 @@ + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` +- { case "$ac_dir" in +- [\\/]* | ?:[\\/]* ) as_incr_dir=;; +- *) as_incr_dir=.;; +-esac +-as_dummy="$ac_dir" +-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do +- case $as_mkdir_dir in +- # Skip DOS drivespec +- ?:) as_incr_dir=$as_mkdir_dir ;; +- *) +- as_incr_dir=$as_incr_dir/$as_mkdir_dir +- test -d "$as_incr_dir" || +- mkdir "$as_incr_dir" || +- { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5 +-echo "$as_me: error: cannot create \"$ac_dir\"" >&2;} +- { (exit 1); exit 1; }; } +- ;; +- esac +-done; } ++ { if $as_mkdir_p; then ++ mkdir -p "$ac_dir" ++ else ++ as_dir="$ac_dir" ++ as_dirs= ++ while test ! -d "$as_dir"; do ++ as_dirs="$as_dir $as_dirs" ++ as_dir=`(dirname "$as_dir") 2>/dev/null || ++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$as_dir" : 'X\(//\)[^/]' \| \ ++ X"$as_dir" : 'X\(//\)$' \| \ ++ X"$as_dir" : 'X\(/\)' \| \ ++ . : '\(.\)' 2>/dev/null || ++echo X"$as_dir" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } ++ /^X\(\/\/\)[^/].*/{ s//\1/; q; } ++ /^X\(\/\/\)$/{ s//\1/; q; } ++ /^X\(\/\).*/{ s//\1/; q; } ++ s/.*/./; q'` ++ done ++ test ! -n "$as_dirs" || mkdir $as_dirs ++ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 ++echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} ++ { (exit 1); exit 1; }; }; } + + ac_builddir=. + +@@ -9712,7 +10101,7 @@ + # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be + # absolute. + ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` ++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` + ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` + ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +@@ -9842,7 +10231,7 @@ + # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be + # absolute. + ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` ++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` + ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` + ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +@@ -9911,25 +10300,30 @@ + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` +- { case $dirpart/$fdir in +- [\\/]* | ?:[\\/]* ) as_incr_dir=;; +- *) as_incr_dir=.;; +-esac +-as_dummy=$dirpart/$fdir +-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do +- case $as_mkdir_dir in +- # Skip DOS drivespec +- ?:) as_incr_dir=$as_mkdir_dir ;; +- *) +- as_incr_dir=$as_incr_dir/$as_mkdir_dir +- test -d "$as_incr_dir" || +- mkdir "$as_incr_dir" || +- { { echo "$as_me:$LINENO: error: cannot create $dirpart/$fdir" >&5 +-echo "$as_me: error: cannot create $dirpart/$fdir" >&2;} +- { (exit 1); exit 1; }; } +- ;; +- esac +-done; } ++ { if $as_mkdir_p; then ++ mkdir -p $dirpart/$fdir ++ else ++ as_dir=$dirpart/$fdir ++ as_dirs= ++ while test ! -d "$as_dir"; do ++ as_dirs="$as_dir $as_dirs" ++ as_dir=`(dirname "$as_dir") 2>/dev/null || ++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$as_dir" : 'X\(//\)[^/]' \| \ ++ X"$as_dir" : 'X\(//\)$' \| \ ++ X"$as_dir" : 'X\(/\)' \| \ ++ . : '\(.\)' 2>/dev/null || ++echo X"$as_dir" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } ++ /^X\(\/\/\)[^/].*/{ s//\1/; q; } ++ /^X\(\/\/\)$/{ s//\1/; q; } ++ /^X\(\/\).*/{ s//\1/; q; } ++ s/.*/./; q'` ++ done ++ test ! -n "$as_dirs" || mkdir $as_dirs ++ fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 ++echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} ++ { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" +@@ -9958,8 +10352,11 @@ + # need to make the FD available again. + if test "$no_create" != yes; then + ac_cs_success=: ++ ac_config_status_args= ++ test "$silent" = yes && ++ ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null +- $SHELL $CONFIG_STATUS || ac_cs_success=false ++ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. +diff -ruN ../gc6.3alpha2/configure.in ./configure.in +--- ../gc6.3alpha2/configure.in Mon Sep 29 14:13:34 2003 ++++ ./configure.in Wed Nov 19 04:17:15 2003 +@@ -275,6 +275,10 @@ + ;; + mips*-*-linux*) + ;; ++ mips-unknown-elf*) ++ machdep="mips2java_mach_dep.lo" ++ AC_DEFINE(MIPS2JAVA) ++ ;; + mips-*-*) + machdep="mips_sgi_mach_dep.lo" + AC_DEFINE(NO_EXECUTE_PERMISSION) +diff -ruN ../gc6.3alpha2/include/private/gcconfig.h ./include/private/gcconfig.h +--- ../gc6.3alpha2/include/private/gcconfig.h Wed Sep 3 14:16:01 2003 ++++ ./include/private/gcconfig.h Wed Nov 19 04:47:25 2003 +@@ -115,7 +115,7 @@ + # if defined(nec_ews) || defined(_nec_ews) + # define EWS4800 + # endif +-# if !defined(LINUX) && !defined(EWS4800) ++# if !defined(LINUX) && !defined(EWS4800) && !defined(MIPS2JAVA) + # if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__) + # define ULTRIX + # else +@@ -1236,6 +1236,16 @@ + + # ifdef MIPS + # define MACH_TYPE "MIPS" ++ ++# ifdef MIPS2JAVA ++extern int _etext[]; ++extern int _end[]; ++# define ALIGNMENT 4 ++# define STACKBOTTOM 0x10000000 ++# define DATASTART (_etext) ++# define DATAEND (_end) ++# endif /* MIPS2JAVA */ ++ + # ifdef LINUX + /* This was developed for a linuxce style platform. Probably */ + /* needs to be tweaked for workstation class machines. */ +diff -ruN ../gc6.3alpha2/mips2java_mach_dep.s ./mips2java_mach_dep.s +--- ../gc6.3alpha2/mips2java_mach_dep.s Wed Dec 31 19:00:00 1969 ++++ ./mips2java_mach_dep.s Wed Nov 19 04:56:28 2003 +@@ -0,0 +1,43 @@ ++ .set noreorder ++ .text ++ .align 2 ++ .globl GC_push_regs ++ .ent GC_push_regs ++GC_push_regs: ++ subu $sp,$sp,24 ++ sw $31,20($sp) ++ ++ jal GC_push_one ++ move $4,$1 ++ jal GC_push_one ++ move $4,$16 ++ jal GC_push_one ++ move $4,$17 ++ jal GC_push_one ++ move $4,$18 ++ jal GC_push_one ++ move $4,$19 ++ jal GC_push_one ++ move $4,$20 ++ jal GC_push_one ++ move $4,$21 ++ jal GC_push_one ++ move $4,$22 ++ jal GC_push_one ++ move $4,$23 ++ jal GC_push_one ++ move $4,$26 ++ jal GC_push_one ++ move $4,$27 ++ jal GC_push_one ++ move $4,$28 ++ jal GC_push_one ++ move $4,$29 ++ jal GC_push_one ++ move $4,$30 ++ ++ lw $31,20($sp) ++ j $31 ++ addu $sp,$sp,24 ++ ++ .end GC_push_regs +diff -ruN ../gc6.3alpha2/os_dep.c ./os_dep.c +--- ../gc6.3alpha2/os_dep.c Mon Sep 22 18:49:47 2003 ++++ ./os_dep.c Wed Nov 19 04:12:13 2003 +@@ -497,7 +497,7 @@ + # if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \ + && !defined(MSWINCE) \ + && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \ +- && !defined(NOSYS) && !defined(ECOS) ++ && !defined(NOSYS) && !defined(ECOS) && !defined(MIPS2JAVA) \ + + # if defined(sigmask) && !defined(UTS4) && !defined(HURD) + /* Use the traditional BSD interface */ diff --git a/upstream/patches/busybox.patch b/upstream/patches/busybox.patch new file mode 100644 index 0000000..ce510eb --- /dev/null +++ b/upstream/patches/busybox.patch @@ -0,0 +1,825 @@ +Only in .: BusyBox.class +Only in .: BusyBox.java +diff -ur ../busybox-0.60.5/Config.h ./Config.h +--- ../busybox-0.60.5/Config.h Tue Sep 17 18:04:28 2002 ++++ ./Config.h Tue Nov 25 11:05:07 2003 +@@ -12,95 +12,95 @@ + #define BB_ASH + #define BB_BASENAME + #define BB_CAT +-#define BB_CHGRP +-#define BB_CHMOD +-#define BB_CHOWN +-#define BB_CHROOT +-#define BB_CHVT ++//#define BB_CHGRP ++//#define BB_CHMOD ++//#define BB_CHOWN ++//#define BB_CHROOT ++//#define BB_CHVT + #define BB_CLEAR +-//#define BB_CMP +-#define BB_CP ++#define BB_CMP ++//#define BB_CP + //#define BB_CPIO + #define BB_CUT + #define BB_DATE + //#define BB_DC +-#define BB_DD ++//#define BB_DD + //#define BB_DEALLOCVT +-#define BB_DF ++//#define BB_DF + #define BB_DIRNAME +-#define BB_DMESG ++//#define BB_DMESG + //#define BB_DOS2UNIX + //#define BB_DPKG + //#define BB_DPKG_DEB + //#define BB_DUTMP +-#define BB_DU ++//#define BB_DU + //#define BB_DUMPKMAP + #define BB_ECHO +-#define BB_ENV ++//#define BB_ENV + //#define BB_EXPR + //#define BB_FBSET + //#define BB_FDFLUSH +-#define BB_FIND +-#define BB_FREE ++//#define BB_FIND ++//#define BB_FREE + //#define BB_FREERAMDISK + //#define BB_FSCK_MINIX + //#define BB_GETOPT + #define BB_GREP +-#define BB_GUNZIP ++//#define BB_GUNZIP + #define BB_GZIP +-#define BB_HALT ++//#define BB_HALT + #define BB_HEAD + //#define BB_HOSTID + //#define BB_HOSTNAME + //#define BB_HUSH +-#define BB_ID ++//#define BB_ID + //#define BB_IFCONFIG +-#define BB_INIT ++//#define BB_INIT + //#define BB_INSMOD +-#define BB_KILL +-#define BB_KILLALL +-#define BB_KLOGD ++//#define BB_KILL ++//#define BB_KILLALL ++//#define BB_KLOGD + //#define BB_LASH + //#define BB_LENGTH +-#define BB_LN ++//#define BB_LN + //#define BB_LOADACM + //#define BB_LOADFONT + //#define BB_LOADKMAP +-#define BB_LOGGER ++//#define BB_LOGGER + //#define BB_LOGNAME + //#define BB_LOSETUP + #define BB_LS +-#define BB_LSMOD ++//#define BB_LSMOD + //#define BB_MAKEDEVS +-//#define BB_MD5SUM ++#define BB_MD5SUM + #define BB_MKDIR + //#define BB_MKFIFO + //#define BB_MKFS_MINIX +-#define BB_MKNOD +-#define BB_MKSWAP ++//#define BB_MKNOD ++//#define BB_MKSWAP + //#define BB_MKTEMP +-#define BB_MODPROBE +-#define BB_MORE +-#define BB_MOUNT ++//#define BB_MODPROBE ++//#define BB_MORE ++//#define BB_MOUNT + //#define BB_MSH + //#define BB_MT +-#define BB_MV ++//#define BB_MV + //#define BB_NC + //#define BB_NSLOOKUP +-#define BB_PIDOF ++//#define BB_PIDOF + //#define BB_PING + //#define BB_PIVOT_ROOT +-#define BB_POWEROFF +-//#define BB_PRINTF +-#define BB_PS +-#define BB_PWD ++//#define BB_POWEROFF ++#define BB_PRINTF ++//#define BB_PS ++//#define BB_PWD + //#define BB_RDATE + //#define BB_READLINK +-#define BB_REBOOT ++//#define BB_REBOOT + //#define BB_RENICE + #define BB_RESET +-#define BB_RM +-#define BB_RMDIR ++//#define BB_RM ++//#define BB_RMDIR + //#define BB_RMMOD + //#define BB_ROUTE + //#define BB_RPM2CPIO +@@ -109,13 +109,13 @@ + #define BB_SLEEP + #define BB_SORT + //#define BB_STTY +-#define BB_SWAPONOFF +-#define BB_SYNC +-#define BB_SYSLOGD ++//#define BB_SWAPONOFF ++//#define BB_SYNC ++//#define BB_SYSLOGD + #define BB_TAIL +-#define BB_TAR +-//#define BB_TEE +-//#define BB_TEST ++//#define BB_TAR ++#define BB_TEE ++#define BB_TEST + //#define BB_TELNET + //#define BB_TFTP + //#define BB_TIME +@@ -124,15 +124,15 @@ + //#define BB_TR + //#define BB_TRACEROUTE + #define BB_TRUE_FALSE +-#define BB_TTY ++//#define BB_TTY + //#define BB_UNIX2DOS + //#define BB_UUENCODE + //#define BB_UUDECODE +-#define BB_UMOUNT ++//#define BB_UMOUNT + #define BB_UNIQ +-#define BB_UNAME ++//#define BB_UNAME + //#define BB_UPDATE +-#define BB_UPTIME ++//#define BB_UPTIME + //#define BB_USLEEP + //#define BB_VI + //#define BB_WATCHDOG +@@ -140,7 +140,7 @@ + //#define BB_WGET + #define BB_WHICH + #define BB_WHOAMI +-#define BB_XARGS ++//#define BB_XARGS + #define BB_YES + // End of Applications List + // +@@ -182,13 +182,13 @@ + //#define BB_FEATURE_USE_DEVPS_PATCH + // + // show verbose usage messages +-#define BB_FEATURE_VERBOSE_USAGE ++//#define BB_FEATURE_VERBOSE_USAGE + // + // Use termios to manipulate the screen ('more' is prettier with this on) + //#define BB_FEATURE_USE_TERMIOS + // + // calculate terminal & column widths (for more, ls, and telnet) +-#define BB_FEATURE_AUTOWIDTH ++//#define BB_FEATURE_AUTOWIDTH + // + // show username/groupnames for ls + #define BB_FEATURE_LS_USERNAME +@@ -271,11 +271,11 @@ + // + // Enable command line editing in the shell. + // Only relevant if a shell is enabled. On by default. +-#define BB_FEATURE_COMMAND_EDITING ++//#define BB_FEATURE_COMMAND_EDITING + // + // Enable tab completion in the shell. This is now working quite nicely. + // This feature adds a bit over 4k. Only relevant if a shell is enabled. +-#define BB_FEATURE_COMMAND_TAB_COMPLETION ++//#define BB_FEATURE_COMMAND_TAB_COMPLETION + // + // Attempts to match usernames in a ~-prefixed path + //#define BB_FEATURE_COMMAND_USERNAME_COMPLETION +@@ -284,7 +284,7 @@ + //were shell builtins. Nice for staticly linking an emergency rescue shell, + //among other things. Off by default. + // Only relevant if a shell is enabled. +-//#define BB_FEATURE_SH_STANDALONE_SHELL ++#define BB_FEATURE_SH_STANDALONE_SHELL + // + //When this is enabled, busybox shell applets can be called using full path + //names. This causes applets (i.e., most busybox commands) to override +@@ -306,7 +306,7 @@ + // are doing is running scripts). Disabing this is bad for interactive + // use, since when you hit ^C in an application, it will also kill the + // shell. This adds about 2.5k on an x86 system. +-#define BB_FEATURE_ASH_JOB_CONTROL ++//#define BB_FEATURE_ASH_JOB_CONTROL + // + //Turn on extra fbset options + //#define BB_FEATURE_FBSET_FANCY +@@ -371,7 +371,7 @@ + #define BB_FEATURE_FIND_TYPE + // + // Support for the find -perm option. +-#define BB_FEATURE_FIND_PERM ++//#define BB_FEATURE_FIND_PERM + // + // Support for the find -mtime option. + #define BB_FEATURE_FIND_MTIME +@@ -420,7 +420,10 @@ + // Nothing beyond this point should ever be touched by + // mere mortals so leave this stuff alone. + // ++#ifdef _GNU_SOURCE + #include ++#endif ++ + #if defined(__uClinux__) + #undef BB_ASH /* Not even a chance it will work */ + #undef BB_RPM2CPIO /* Uses gz_open(), which uses fork() */ +diff -ur ../busybox-0.60.5/Makefile ./Makefile +--- ../busybox-0.60.5/Makefile Sun Oct 27 00:47:54 2002 ++++ ./Makefile Tue Nov 25 11:27:30 2003 +@@ -49,7 +49,7 @@ + # just 1.4k to the binary size (which is a _lot_ less then glibc NSS costs). + # Note that if you want hostname resolution to work with glibc, you still need + # the libnss_* libraries. +-USE_SYSTEM_PWD_GRP = true ++USE_SYSTEM_PWD_GRP = false + + # This enables compiling with dmalloc ( http://dmalloc.com/ ) + # which is an excellent public domain mem leak and malloc problem +@@ -83,7 +83,7 @@ + + # If you are running a cross compiler, you may want to set this + # to something more interesting, like "powerpc-linux-". +-CROSS = ++CROSS = mips-unknown-elf- + CC = $(CROSS)gcc + AR = $(CROSS)ar + STRIP = $(CROSS)strip +@@ -106,11 +106,11 @@ + # + # For other libraries, you are on your own... + #LDFLAGS+=-nostdlib +-#LIBRARIES = $(LIBCDIR)/lib/libc.a -lgcc ++LIBRARIES = -lglob -lregex + #CROSS_CFLAGS+=-nostdinc -I$(LIBCDIR)/include -I$(GCCINCDIR) + #GCCINCDIR = $(shell gcc -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp") + +-WARNINGS = -Wall -Wshadow ++WARNINGS = -Wall -Wshadow -Werror -Wno-unused + + ARFLAGS = -r + +@@ -181,9 +181,9 @@ + LDFLAGS += -Wl,-warn-common + STRIPCMD = /bin/true -Since_we_are_debugging + else +- CFLAGS += $(WARNINGS) $(OPTIMIZATIONS) -D_GNU_SOURCE +- LDFLAGS += -s -Wl,-warn-common +- STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment ++ CFLAGS += $(WARNINGS) $(OPTIMIZATIONS) -DNEWLIB_ASH ++ LDFLAGS += -Wl,-warn-common ++ STRIPCMD = true + endif + ifeq ($(strip $(DOSTATIC)),true) + LDFLAGS += --static +@@ -260,7 +260,7 @@ + PWD_LIB = libpwd.a + PWD_CSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c \ + fgetpwent.c __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c \ +- initgroups.c setgroups.c ++ initgroups.c + PWD_OBJS=$(patsubst %.c,$(PWD_GRP)/%.o, $(PWD_CSRC)) + ifneq ($(strip $(BB_SRC_DIR)),) + PWD_CFLAGS = -I- -I. +@@ -273,19 +273,19 @@ + LIBBB = libbb + LIBBB_LIB = libbb.a + LIBBB_CSRC= ask_confirmation.c chomp.c concat_path_file.c copy_file.c \ +-copy_file_chunk.c libc5.c device_open.c error_msg.c inode_hash.c \ +-error_msg_and_die.c fgets_str.c find_mount_point.c find_pid_by_name.c \ +-find_root_device.c full_read.c full_write.c get_console.c \ ++copy_file_chunk.c device_open.c error_msg.c inode_hash.c \ ++error_msg_and_die.c fgets_str.c find_pid_by_name.c \ ++find_root_device.c full_read.c full_write.c \ + get_last_path_component.c get_line_from_file.c gz_open.c human_readable.c \ +-isdirectory.c kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c \ ++isdirectory.c mode_string.c \ + mtab_file.c my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c \ + my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \ + print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \ +-safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \ ++safe_read.c safe_strncpy.c time_string.c \ + trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ +-xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ +-copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ +-dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ ++xgetcwd.c xreadlink.c xregcomp.c remove_file.c last_char_is.c \ ++copyfd.c herror_msg.c herror_msg_and_die.c \ ++dirname.c make_directory.c u_signal_names.c arith.c \ + simplify_path.c + LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) + ifeq ($(strip $(BB_SRC_DIR)),) +diff -ur ../busybox-0.60.5/ash.c ./ash.c +--- ../busybox-0.60.5/ash.c Tue Oct 22 18:14:29 2002 ++++ ./ash.c Tue Nov 25 11:17:08 2003 +@@ -84,11 +84,15 @@ + #include + #include + #include ++#ifndef NEWLIB_ASH + #include ++#endif + #include + #include + #include ++#ifndef NEWLIB_ASH + #include ++#endif + #include + #include + #include +@@ -268,6 +272,7 @@ + * more fun than worrying about efficiency and portability. :-)) + */ + ++#ifndef NEWLIB_ASH + static void onint(void); + static volatile int suppressint; + static volatile int intpending; +@@ -287,6 +292,16 @@ + #define CLEAR_PENDING_INT intpending = 0 + #define int_pending() intpending + ++#else ++ ++#define INTON ++#define INTOFF ++#define FORCEINTON ++#define CLEAR_PENDING_INT ++#define int_pending() 0 ++ ++#endif ++ + + typedef void *pointer; + +@@ -1556,7 +1571,9 @@ + #endif + static int unsetcmd(int, char **); + static int waitcmd(int, char **); ++#ifndef NEWLIB_ASH + static int ulimitcmd(int, char **); ++#endif + static int timescmd(int, char **); + + #ifdef CONFIG_ASH_MATH_SUPPORT +@@ -1647,10 +1664,14 @@ + {BUILTIN_NOSPEC "setvar", setvarcmd}, + {BUILTIN_SPECIAL "shift", shiftcmd}, + {BUILTIN_SPECIAL "times", timescmd}, ++#ifndef NEWLIB_ASH + {BUILTIN_SPECIAL "trap", trapcmd}, ++#endif + {BUILTIN_REGULAR "true", true_main}, + {BUILTIN_NOSPEC "type", typecmd}, ++#ifndef NEWLIB_ASH + {BUILTIN_NOSPEC "ulimit", ulimitcmd}, ++#endif + {BUILTIN_REGULAR "umask", umaskcmd}, + #ifdef CONFIG_ASH_ALIAS + {BUILTIN_REGULAR "unalias", unaliascmd}, +@@ -1918,6 +1939,8 @@ + * just defensive programming.) + */ + ++#ifndef NEWLIB_ASH ++ + static void onint(void) + { + sigset_t mysigset; +@@ -1937,6 +1960,7 @@ + /* NOTREACHED */ + } + ++#endif + + static char *commandname; /* currently executing command */ + +@@ -2086,7 +2110,7 @@ + } + + +-#ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE ++#if defined(CONFIG_ASH_OPTIMIZE_FOR_SIZE) && !defined(NEWLIB_ASH) + static void __inton() + { + if (--suppressint == 0 && intpending) { +@@ -5597,7 +5621,6 @@ + + static void init(void) + { +- + /* from cd.c: */ + { + curdir = nullstr; +@@ -5621,8 +5644,10 @@ + } + } + ++#ifndef NEWLIB_ASH + snprintf(ppid, sizeof(ppid), "%d", (int) getppid()); + setvar("PPID", ppid, 0); ++#endif + } + } + +@@ -6214,12 +6239,16 @@ + else /* WIFSIGNALED(ps->status) */ + #endif + i = WTERMSIG(ps->status); ++#ifndef NEWLIB_ASH + if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) + strcpy(s, sys_siglist[i & 0x7F]); + else ++#endif + snprintf(s, 64, "Signal %d", i & 0x7F); ++#ifndef NEWLIB_ASH + if (WCOREDUMP(ps->status)) + strcat(s, " (core dumped)"); ++#endif + } + out1str(s); + col += strlen(s); +@@ -6641,7 +6670,11 @@ + #endif + if (block == 0) + flags |= WNOHANG; ++#ifndef NEWLIB_ASH + return wait3(status, flags, (struct rusage *) NULL); ++#else ++ return waitpid(-1,status,flags); ++#endif + } + + static int dowait(int block, struct job *job) +@@ -6700,7 +6733,9 @@ + } + INTON; + if (!rootshell || !iflag || (job && thisjob == job)) { ++#ifndef NEWLIB_ASH + core = WCOREDUMP(status); ++#endif + #ifdef BB_FEATURE_ASH_JOB_CONTROL + if (WIFSTOPPED(status)) + sig = WSTOPSIG(status); +@@ -6718,12 +6753,16 @@ + if (sig == SIGTSTP && rootshell && iflag) + out2fmt("%%%ld ", (long) (job - jobtab + 1)); + #endif ++#ifndef NEWLIB_ASH + if (sig < NSIG && sys_siglist[sig]) + out2str(sys_siglist[sig]); + else ++#endif + out2fmt("Signal %d", sig); ++#ifndef NEWLIB_ASH + if (core) + out2str(" - core dumped"); ++#endif + out2c('\n'); + } else { + TRACE(("Not printing status: status=%d, sig=%d\n", status, sig)); +@@ -7993,6 +8032,8 @@ + {NULL, 0, 0} + }; + ++#ifndef NEWLIB_ASH ++ + static int ulimitcmd(int argc, char **argv) + { + static const char unlimited_string[] = "unlimited"; +@@ -8118,6 +8159,8 @@ + return 0; + } + ++#endif /* !NEWLIB_ASH */ ++ + /* + * prefix -- see if pfx is a prefix of string. + */ +@@ -11426,6 +11469,8 @@ + * The trap builtin. + */ + ++#ifndef NEWLIB_ASH ++ + static int trapcmd(int argc, char **argv) + { + char *action; +@@ -11475,6 +11520,7 @@ + return 0; + } + ++#endif /*!NEWLIB_ASH */ + + /* + * Set the signal handler for the specified signal. The routine figures +@@ -11485,7 +11531,9 @@ + { + int action; + char *t; ++#ifndef NEWLIB_ASH + struct sigaction act; ++#endif + + if ((t = trap[signo]) == NULL) + action = S_DFL; +@@ -11527,6 +11575,7 @@ + /* + * current setting unknown + */ ++#ifndef NEWLIB_ASH + if (sigaction(signo, 0, &act) == -1) { + /* + * Pretend it worked; maybe we should give a warning +@@ -11536,6 +11585,7 @@ + return; + } + if (act.sa_handler == SIG_IGN) { ++ + if (mflag && (signo == SIGTSTP || + signo == SIGTTIN || signo == SIGTTOU)) { + *t = S_IGN; /* don't hard ignore these */ +@@ -11544,15 +11594,22 @@ + } else { + *t = S_RESET; /* force to be set */ + } ++#else ++ *t = S_DFL; ++#endif + } + if (*t == S_HARD_IGN || *t == action) + return; ++ *t = action; ++#ifndef NEWLIB_ASH + act.sa_handler = ((action == S_CATCH) ? onsig + : ((action == S_IGN) ? SIG_IGN : SIG_DFL)); +- *t = action; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(signo, &act, 0); ++#else ++ signal(signo,((action == S_CATCH) ? onsig : ((action == S_IGN) ? SIG_IGN : SIG_DFL))); ++#endif + } + + /* +@@ -11574,10 +11631,12 @@ + + static void onsig(int signo) + { ++#ifndef NEWLIB_ASH + if (signo == SIGINT && trap[SIGINT] == NULL) { + onint(); + return; + } ++#endif + gotsig[signo - 1] = 1; + pendingsigs++; + } +@@ -12153,6 +12212,7 @@ + + static struct var **findvar(struct var **vpp, const char *name) + { ++ int n=0; + for (; *vpp; vpp = &(*vpp)->next) { + if (varequal((*vpp)->text, name)) { + break; +@@ -12168,8 +12228,11 @@ + static int timescmd(int argc, char **argv) + { + struct tms buf; ++#ifdef NEWLIB_ASH ++ long int clk_tck = _CLOCKS_PER_SEC_; ++#else + long int clk_tck = sysconf(_SC_CLK_TCK); +- ++#endif + times(&buf); + printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", + (int) (buf.tms_utime / clk_tck / 60), +diff -ur ../busybox-0.60.5/busybox.h ./busybox.h +--- ../busybox-0.60.5/busybox.h Fri Mar 15 21:11:46 2002 ++++ ./busybox.h Tue Nov 25 11:10:52 2003 +@@ -37,8 +37,9 @@ + #include "dmalloc.h" + #endif + ++#ifdef _GNU_SOURCE + #include +- ++#endif + + enum Location { + _BB_DIR_ROOT = 0, +@@ -85,7 +86,9 @@ + + /* Bit map related macros -- libc5 doens't provide these... sigh. */ + #ifndef setbit ++#ifndef NBBY + #define NBBY CHAR_BIT ++#endif + #define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) + #define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) + #define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +Only in ../busybox-0.60.5: busybox.links +diff -ur ../busybox-0.60.5/busybox.sh ./busybox.sh +--- ../busybox-0.60.5/busybox.sh Wed Sep 26 02:20:54 2001 ++++ ./busybox.sh Tue Nov 25 10:57:58 2003 +@@ -5,7 +5,7 @@ + + RAW=` \ + $CC -E -dM ${1:-Config.h} | \ +- sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*\/\1.c/gp;' \ ++ sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*BB_\([A-Z0-9_]*\)/\1.c/gp;' \ + | tr A-Z a-z | sort + ` + test "${RAW}" != "" || exit +diff -ur ../busybox-0.60.5/date.c ./date.c +--- ../busybox-0.60.5/date.c Sat Jun 15 10:35:13 2002 ++++ ./date.c Tue Nov 25 11:26:25 2003 +@@ -210,9 +210,7 @@ + + /* if setting time, set it */ + if (set_time) { +- if (stime(&tm) < 0) { +- perror_msg("cannot set date"); +- } ++ perror_msg("cannot set date"); + } + } + +Only in ../busybox-0.60.5/docs: BusyBox.1 +Only in ../busybox-0.60.5/docs: BusyBox.html +Only in ../busybox-0.60.5/docs: BusyBox.txt +Only in ../busybox-0.60.5/docs: busybox.pod +diff -ur ../busybox-0.60.5/libbb/libbb.h ./libbb/libbb.h +--- ../busybox-0.60.5/libbb/libbb.h Wed Sep 18 15:21:07 2002 ++++ ./libbb/libbb.h Tue Nov 25 11:10:27 2003 +@@ -25,8 +25,6 @@ + #include + #include + +-#include +- + #ifndef _BB_INTERNAL_H_ + #include "../busybox.h" + #endif +@@ -35,7 +33,9 @@ + #include "dmalloc.h" + #endif + ++#ifdef _GNU_SOURCE + #include ++#endif + + #if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) + /* libc5 doesn't define socklen_t */ +diff -ur ../busybox-0.60.5/ls.c ./ls.c +--- ../busybox-0.60.5/ls.c Mon Sep 16 01:53:01 2002 ++++ ./ls.c Tue Nov 25 11:29:41 2003 +@@ -43,7 +43,7 @@ + + enum { + TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ +- COLUMN_WIDTH = 14, /* default if AUTOWIDTH not defined */ ++ COLUMN_WIDTH = 18, /* default if AUTOWIDTH not defined */ + COLUMN_GAP = 2, /* includes the file type char */ + }; + +@@ -61,8 +61,10 @@ + #include + #include + #include ++#ifdef BB_FEATURE_AUTOWIDTH + #include + #include ++#endif + #include "busybox.h" + + #ifdef BB_FEATURE_LS_TIMESTAMPS +@@ -484,7 +486,7 @@ + column_width = COLUMN_WIDTH; + } + #else +- ncols= TERMINAL_WIDTH; ++ ncols= (int) (TERMINAL_WIDTH / (COLUMN_WIDTH+COLUMN_GAP)); + #endif + switch (style_fmt) { + case STYLE_LONG: /* one record per line, extended info */ +diff -ur ../busybox-0.60.5/md5sum.c ./md5sum.c +--- ../busybox-0.60.5/md5sum.c Tue Oct 22 18:13:57 2002 ++++ ./md5sum.c Tue Nov 25 11:22:37 2003 +@@ -44,13 +44,17 @@ + #include + #include + #include +-#include + #include + #if defined HAVE_LIMITS_H + # include + #endif + #include "busybox.h" + ++typedef unsigned int u_int32_t; ++#ifndef __P ++#define __P(x) x ++#endif ++ + /* For some silly reason, this file uses backwards TRUE and FALSE conventions */ + #undef TRUE + #undef FALSE +@@ -146,11 +150,7 @@ + //---------------------------------------------------------------------------- + + /* Handle endian-ness */ +-#if __BYTE_ORDER == __LITTLE_ENDIAN +- #define SWAP(n) (n) +-#else +- #define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24)) +-#endif ++#define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24)) + + + +diff -ur ../busybox-0.60.5/printf.c ./printf.c +--- ../busybox-0.60.5/printf.c Mon Mar 19 14:25:49 2001 ++++ ./printf.c Tue Nov 25 11:22:49 2003 +@@ -57,6 +57,10 @@ + #include + #include "busybox.h" + ++#ifndef __P ++#define __P(x) x ++#endif ++ + + #ifndef S_IFMT + static const int S_IFMT = 0170000; +diff -ur ../busybox-0.60.5/pwd_grp/grp.h ./pwd_grp/grp.h +--- ../busybox-0.60.5/pwd_grp/grp.h Sat Jan 27 03:24:39 2001 ++++ ./pwd_grp/grp.h Tue Nov 25 11:05:36 2003 +@@ -5,8 +5,14 @@ + #include + #else + ++#ifndef __P ++#define __P(x) x ++#endif ++ + #include ++#ifdef _GNU_SOURCE + #include ++#endif + #include + + /* The group structure */ +diff -ur ../busybox-0.60.5/pwd_grp/pwd.h ./pwd_grp/pwd.h +--- ../busybox-0.60.5/pwd_grp/pwd.h Sat Jan 27 03:24:39 2001 ++++ ./pwd_grp/pwd.h Tue Nov 25 11:05:09 2003 +@@ -5,8 +5,14 @@ + #include + #else + ++#ifndef __P ++#define __P(x) x ++#endif ++ + #include ++#ifdef _GNU_SOURCE + #include ++#endif + #include + + /* The passwd structure. */ diff --git a/upstream/patches/freetype.patch b/upstream/patches/freetype.patch new file mode 100644 index 0000000..caefc0d --- /dev/null +++ b/upstream/patches/freetype.patch @@ -0,0 +1,25 @@ +--- include/freetype/config/ftmodule.h Thu Jul 31 12:59:06 2003 ++++ include/freetype/config/ftmodule.h Thu Jul 31 12:59:17 2003 +@@ -1,4 +1,5 @@ + FT_USE_MODULE(autohint_module_class) ++/* + FT_USE_MODULE(cff_driver_class) + FT_USE_MODULE(t1cid_driver_class) + FT_USE_MODULE(pcf_driver_class) +@@ -7,13 +8,15 @@ + FT_USE_MODULE(psnames_module_class) + FT_USE_MODULE(pshinter_module_class) + FT_USE_MODULE(ft_raster1_renderer_class) ++*/ + FT_USE_MODULE(sfnt_module_class) + FT_USE_MODULE(ft_smooth_renderer_class) + FT_USE_MODULE(ft_smooth_lcd_renderer_class) + FT_USE_MODULE(ft_smooth_lcdv_renderer_class) + FT_USE_MODULE(tt_driver_class) ++/* + FT_USE_MODULE(t1_driver_class) + FT_USE_MODULE(t42_driver_class) + FT_USE_MODULE(pfr_driver_class) + FT_USE_MODULE(winfnt_driver_class) +- ++*/ diff --git a/upstream/patches/ft-nostdio.patch b/upstream/patches/ft-nostdio.patch new file mode 100644 index 0000000..6098c50 --- /dev/null +++ b/upstream/patches/ft-nostdio.patch @@ -0,0 +1,83 @@ +--- src/base/ftsystem.c.origf Mon Dec 29 05:45:54 2003 ++++ src/base/ftsystem.c Mon Dec 29 05:46:08 2003 +@@ -32,7 +32,8 @@ + #include FT_ERRORS_H + #include FT_TYPES_H + +-#include ++#include ++#include + #include + + +@@ -151,7 +152,7 @@ + + /* We use the macro STREAM_FILE for convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object */ +-#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) ++#define STREAM_FD( stream ) ( (int)stream->descriptor.value ) + + + /*************************************************************************/ +@@ -168,7 +169,7 @@ + FT_CALLBACK_DEF( void ) + ft_ansi_stream_close( FT_Stream stream ) + { +- fclose( STREAM_FILE( stream ) ); ++ close(STREAM_FD(stream)); + + stream->descriptor.pointer = NULL; + stream->size = 0; +@@ -202,14 +203,14 @@ + unsigned char* buffer, + unsigned long count ) + { +- FILE* file; ++ int fd; + + +- file = STREAM_FILE( stream ); ++ fd = STREAM_FD( stream ); + +- fseek( file, offset, SEEK_SET ); ++ if(lseek( fd, offset, SEEK_SET ) < 0) return 0; + +- return (unsigned long)fread( buffer, 1, count, file ); ++ return (unsigned long) read(fd,buffer,count); + } + + +@@ -219,14 +220,14 @@ + FT_Stream_Open( FT_Stream stream, + const char* filepathname ) + { +- FILE* file; ++ int fd,n; + + + if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + +- file = fopen( filepathname, "rb" ); +- if ( !file ) ++ fd = open( filepathname, O_RDONLY); ++ if (fd < 0) + { + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); +@@ -234,11 +235,11 @@ + return FT_Err_Cannot_Open_Resource; + } + +- fseek( file, 0, SEEK_END ); +- stream->size = ftell( file ); +- fseek( file, 0, SEEK_SET ); ++ n = lseek( fd, 0, SEEK_END ); ++ stream-> size = n < 0 ? 0 : n; ++ lseek( fd, 0, SEEK_SET ); + +- stream->descriptor.pointer = file; ++ stream->descriptor.value = fd; + stream->pathname.pointer = (char*)filepathname; + stream->pos = 0; + diff --git a/upstream/patches/gcc-fdata-sections-bss.patch b/upstream/patches/gcc-fdata-sections-bss.patch new file mode 100644 index 0000000..d921ae6 --- /dev/null +++ b/upstream/patches/gcc-fdata-sections-bss.patch @@ -0,0 +1,30 @@ +--- gcc/config/mips/mips.c.orig Mon Dec 29 06:30:42 2003 ++++ gcc/config/mips/mips.c Mon Dec 29 07:16:35 2003 +@@ -10535,11 +10535,13 @@ + int len, size, sec; + const char *name, *prefix; + char *string; +- static const char *const prefixes[4][2] = { ++ static const char *const prefixes[6][2] = { + { ".text.", ".gnu.linkonce.t." }, + { ".rodata.", ".gnu.linkonce.r." }, + { ".data.", ".gnu.linkonce.d." }, +- { ".sdata.", ".gnu.linkonce.s." } ++ { ".sdata.", ".gnu.linkonce.s." }, ++ { ".bss.", ".gnu.linkonce.b." }, ++ { ".sbss.", ".gnu.linkonce.sb." } + }; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); +@@ -10551,8 +10553,9 @@ + if (TREE_CODE (decl) == FUNCTION_DECL) + sec = 0; + else if (DECL_INITIAL (decl) == 0 +- || DECL_INITIAL (decl) == error_mark_node) +- sec = 2; ++ || DECL_INITIAL (decl) == error_mark_node ++ || initializer_zerop (DECL_INITIAL (decl))) ++ sec = (size > 0 && size <= mips_section_threshold) ? 5 : 4; + else if ((TARGET_EMBEDDED_PIC || TARGET_MIPS16) + && TREE_CODE (decl) == STRING_CST + && !flag_writable_strings) diff --git a/upstream/patches/gcc-fixes.patch b/upstream/patches/gcc-fixes.patch new file mode 100644 index 0000000..ab6a652 --- /dev/null +++ b/upstream/patches/gcc-fixes.patch @@ -0,0 +1,65 @@ +diff -urN ../gcc-3.3.1/gcc/builtin-attrs.def ./gcc/builtin-attrs.def +--- ../gcc-3.3.1/gcc/builtin-attrs.def Tue Mar 4 09:37:20 2003 ++++ ./gcc/builtin-attrs.def Wed Aug 27 00:09:45 2003 +@@ -110,6 +110,7 @@ + ATTR_NOTHROW_LIST) + + /* Construct a tree for a format attribute. */ ++#if 0 + #define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES) \ + DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL, \ + CONCAT2 (ATTR_,TYPE), CONCAT2 (ATTR_LIST_,VALUES)) \ +@@ -128,6 +129,32 @@ + DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0) + DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4) + #undef DEF_FORMAT_ATTRIBUTE ++#else ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_1_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_1_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_1_0, ATTR_FORMAT, ATTR_PRINTF_1_0, ATTR_NONNULL_1) ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_1_2, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_1_2) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_1_2, ATTR_FORMAT, ATTR_PRINTF_1_2, ATTR_NONNULL_1) ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_2_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_2_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_2_0, ATTR_FORMAT, ATTR_PRINTF_2_0, ATTR_NONNULL_2) ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_2_3, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_2_3) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_2_3, ATTR_FORMAT, ATTR_PRINTF_2_3, ATTR_NONNULL_2) ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_3_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_3_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_3_0, ATTR_FORMAT, ATTR_PRINTF_3_0, ATTR_NONNULL_3) ++DEF_ATTR_TREE_LIST (ATTR_PRINTF_3_4, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_3_4) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_3_4, ATTR_FORMAT, ATTR_PRINTF_3_4, ATTR_NONNULL_3) ++DEF_ATTR_TREE_LIST (ATTR_SCANF_1_0, ATTR_NULL, ATTR_SCANF, ATTR_LIST_1_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_1_0, ATTR_FORMAT, ATTR_SCANF_1_0, ATTR_NONNULL_1) ++DEF_ATTR_TREE_LIST (ATTR_SCANF_1_2, ATTR_NULL, ATTR_SCANF, ATTR_LIST_1_2) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_1_2, ATTR_FORMAT, ATTR_SCANF_1_2, ATTR_NONNULL_1) ++DEF_ATTR_TREE_LIST (ATTR_SCANF_2_0, ATTR_NULL, ATTR_SCANF, ATTR_LIST_2_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_2_0, ATTR_FORMAT, ATTR_SCANF_2_0, ATTR_NONNULL_2) ++DEF_ATTR_TREE_LIST (ATTR_SCANF_2_3, ATTR_NULL, ATTR_SCANF, ATTR_LIST_2_3) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_2_3, ATTR_FORMAT, ATTR_SCANF_2_3, ATTR_NONNULL_2) ++DEF_ATTR_TREE_LIST (ATTR_STRFTIME_3_0, ATTR_NULL, ATTR_STRFTIME, ATTR_LIST_3_0) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_STRFTIME_3_0, ATTR_FORMAT, ATTR_STRFTIME_3_0, ATTR_NONNULL_3) ++DEF_ATTR_TREE_LIST (ATTR_STRFMON_3_4, ATTR_NULL, ATTR_STRFMON, ATTR_LIST_3_4) ++DEF_ATTR_TREE_LIST (ATTR_FORMAT_STRFMON_3_4, ATTR_FORMAT, ATTR_STRFMON_3_4, ATTR_NONNULL_3) ++#endif + + /* Construct a tree for a format_arg attribute. */ + #define DEF_FORMAT_ARG_ATTRIBUTE(FA) \ +diff -urN ../gcc-3.3.1/gcc/config/mips/t-unknown ./gcc/config/mips/t-unknown +--- ../gcc-3.3.1/gcc/config/mips/t-unknown Wed Dec 31 19:00:00 1969 ++++ ./gcc/config/mips/t-unknown Mon Sep 1 01:19:35 2003 +@@ -0,0 +1,3 @@ ++MULTILIB_OPTIONS= ++MULTILIB_DIRNAMES = ++MULTILIB_MATCHES = +diff -urN ../gcc-3.3.1/gcc/config.gcc ./gcc/config.gcc +--- ../gcc-3.3.1/gcc/config.gcc Fri Jun 27 07:44:22 2003 ++++ ./gcc/config.gcc Sun Aug 31 12:39:12 2003 +@@ -1932,6 +1932,10 @@ + target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS" + tm_defines="MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64" + ;; ++mips*-unknown-elf*) ++ tm_file="${tm_file} mips/elf.h" ++ tmake_file="mips/t-elf mips/t-unknown" ++ ;; + mips-*-elf* | mipsel-*-elf*) + tm_file="${tm_file} mips/elf.h" + tmake_file=mips/t-elf diff --git a/upstream/patches/libmspack.patch b/upstream/patches/libmspack.patch new file mode 100644 index 0000000..cb40f62 --- /dev/null +++ b/upstream/patches/libmspack.patch @@ -0,0 +1,25 @@ +--- ../libmspack.orig/mspack/Makefile Sat Jul 26 10:44:57 2003 ++++ mspack/Makefile Sun Nov 2 17:12:35 2003 +@@ -1,12 +1,13 @@ + CC=gcc + RM=rm -f + AR=ar ++RANLIB=ranlib + + WARNINGS=-Wall -Wsign-compare -Wconversion -pedantic + LARGEFILE=-std=c99 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + DEBUG=-g -DDEBUG + OPTIM=-O3 +-CFLAGS= $(WARNINGS) $(LARGEFILE) $(DEBUG) $(OPTIM) -I. ++CFLAGS= $(WARNINGS) $(LARGEFILE) $(OPTIM) -I. #-DMSPACK_NO_DEFAULT_SYSTEM + + all: libmspack.a + +@@ -27,6 +28,7 @@ + libmspack.a: $(OBJS) + -$(RM) $@ + $(AR) q $@ $(OBJS) ++ $(RANLIB) $@ + + .c.o: + $(CC) $(CFLAGS) -o $@ -c $< diff --git a/upstream/patches/newlib-malloc.patch b/upstream/patches/newlib-malloc.patch new file mode 100644 index 0000000..fdf36be --- /dev/null +++ b/upstream/patches/newlib-malloc.patch @@ -0,0 +1,21 @@ +--- newlib/libc/stdlib/mallocr.c.old Sun Nov 23 18:41:21 2003 ++++ newlib/libc/stdlib/mallocr.c Sun Nov 23 18:43:03 2003 +@@ -301,7 +301,8 @@ + #define SEPARATE_OBJECTS + #define HAVE_MMAP 0 + #define MORECORE(size) _sbrk_r(reent_ptr, (size)) +-#define MORECORE_CLEARS 0 ++#define MORECORE_CLEARS 1 ++#define malloc_getpagesize getpagesize() + #define MALLOC_LOCK __malloc_lock(reent_ptr) + #define MALLOC_UNLOCK __malloc_unlock(reent_ptr) + +@@ -310,7 +311,7 @@ + # undef WIN32 + #endif + +-#ifndef _WIN32 ++#if !defined(_WIN32) && !defined(malloc_getpagesize) + #ifdef SMALL_MEMORY + #define malloc_getpagesize (128) + #else diff --git a/upstream/patches/newlib-mips.patch b/upstream/patches/newlib-mips.patch new file mode 100644 index 0000000..474d0d3 --- /dev/null +++ b/upstream/patches/newlib-mips.patch @@ -0,0 +1,2863 @@ +diff -urN ../newlib-1.11.0.orig/libgloss/configure ./libgloss/configure +--- ../newlib-1.11.0.orig/libgloss/configure Tue Nov 25 09:05:13 2003 ++++ ./libgloss/configure Mon Nov 24 20:12:14 2003 +@@ -762,6 +762,9 @@ + mips*-*-pe) + configdirs="wince" + ;; ++ mips*-unknown-elf*) ++ configdirs="${configdirs}" ++ ;; + mips*-*-*) + configdirs="${configdirs} mips testsuite" + ;; +@@ -818,7 +821,7 @@ + # Extract the first word of "gcc", so it can be a program name with args. + set dummy gcc; ac_word=$2 + echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +-echo "configure:822: checking for $ac_word" >&5 ++echo "configure:825: checking for $ac_word" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +@@ -848,7 +851,7 @@ + # Extract the first word of "cc", so it can be a program name with args. + set dummy cc; ac_word=$2 + echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +-echo "configure:852: checking for $ac_word" >&5 ++echo "configure:855: checking for $ac_word" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +@@ -897,7 +900,7 @@ + fi + + echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +-echo "configure:901: checking whether we are using GNU C" >&5 ++echo "configure:904: checking whether we are using GNU C" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +@@ -906,7 +909,7 @@ + yes; + #endif + EOF +-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ++if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes + else + ac_cv_prog_gcc=no +@@ -921,7 +924,7 @@ + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +-echo "configure:925: checking whether ${CC-cc} accepts -g" >&5 ++echo "configure:928: checking whether ${CC-cc} accepts -g" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +@@ -953,7 +956,7 @@ + # Extract the first word of "ar", so it can be a program name with args. + set dummy ar; ac_word=$2 + echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +-echo "configure:957: checking for $ac_word" >&5 ++echo "configure:960: checking for $ac_word" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +@@ -987,7 +990,7 @@ + # Extract the first word of "ranlib", so it can be a program name with args. + set dummy ranlib; ac_word=$2 + echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +-echo "configure:991: checking for $ac_word" >&5 ++echo "configure:994: checking for $ac_word" >&5 + if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else +diff -urN ../newlib-1.11.0.orig/libgloss/configure.in ./libgloss/configure.in +--- ../newlib-1.11.0.orig/libgloss/configure.in Tue Nov 25 09:05:13 2003 ++++ ./libgloss/configure.in Mon Nov 24 20:12:14 2003 +@@ -73,6 +73,9 @@ + mips*-*-pe) + configdirs="wince" + ;; ++ mips*-unknown-elf*) ++ configdirs="${configdirs}" ++ ;; + mips*-*-*) + configdirs="${configdirs} mips testsuite" + ;; +diff -urN ../newlib-1.11.0.orig/newlib/configure.host ./newlib/configure.host +--- ../newlib-1.11.0.orig/newlib/configure.host Tue Nov 25 09:05:13 2003 ++++ ./newlib/configure.host Tue Nov 25 08:30:02 2003 +@@ -356,6 +356,9 @@ + m8*-bug-*) + sys_dir=m88kbug + ;; ++ mips*-unknown-elf*) ++ sys_dir=mipsunknown ++ ;; + mips*-dec-*) + sys_dir=decstation + ;; +@@ -508,6 +511,10 @@ + newlib_cflags="${newlib_cflags}" + syscall_dir=syscalls + ;; ++ mips*-unknown-elf*) ++ newlib_cflags="${newlib_cflags} -DREENTRANT_SYSCALLS_PROVIDED -DHAVE_GETTIMEOFDAY -DHAVE_FCNTL" ++ syscall_dir=syscalls ++ ;; + mmix-*) + syscall_dir=syscalls + # We need every symbol 32-bit aligned, so the invalid +diff -urN ../newlib-1.11.0.orig/newlib/libc/include/paths.h ./newlib/libc/include/paths.h +--- ../newlib-1.11.0.orig/newlib/libc/include/paths.h Thu Feb 17 14:39:46 2000 ++++ ./newlib/libc/include/paths.h Tue Nov 25 09:48:09 2003 +@@ -3,5 +3,6 @@ + + #define _PATH_DEV "/dev/" + #define _PATH_BSHELL "/bin/sh" ++#define _PATH_DEVNULL "/dev/null" + + #endif /* _PATHS_H_ */ +diff -urN ../newlib-1.11.0.orig/newlib/libc/include/stdlib.h ./newlib/libc/include/stdlib.h +--- ../newlib-1.11.0.orig/newlib/libc/include/stdlib.h Fri Dec 6 13:58:50 2002 ++++ ./newlib/libc/include/stdlib.h Tue Nov 25 09:50:46 2003 +@@ -158,10 +158,12 @@ + _VOID _EXFUN(cfree,(_PTR)); + #else + char * _EXFUN(realpath,(const char *, char *)); ++#endif + void _EXFUN(unsetenv,(const char *__string)); + void _EXFUN(_unsetenv_r,(struct _reent *, const char *__string)); + int _EXFUN(random,(_VOID)); + long _EXFUN(srandom,(unsigned __seed)); ++#ifdef __CYGWIN__ + char * _EXFUN(ptsname, (int)); + int _EXFUN(grantpt, (int)); + int _EXFUN(unlockpt,(int)); +diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/signal.h ./newlib/libc/include/sys/signal.h +--- ../newlib-1.11.0.orig/newlib/libc/include/sys/signal.h Wed Jul 24 14:18:07 2002 ++++ ./newlib/libc/include/sys/signal.h Tue Nov 25 09:56:00 2003 +@@ -142,6 +142,8 @@ + int _EXFUN(pthread_sigmask, (int how, const sigset_t *set, sigset_t *oset)); + #endif + ++int _EXFUN(kill, (int, int)); ++ + /* protos for functions found in winsup sources for CYGWIN */ + #if defined(__CYGWIN__) || defined(__rtems__) + #undef sigaddset +@@ -150,7 +152,6 @@ + always defines pid_t to be int. If that ever + changes, then we will need to do something else, perhaps along the + lines of . */ +-int _EXFUN(kill, (int, int)); + int _EXFUN(killpg, (pid_t, int)); + int _EXFUN(sigaction, (int, const struct sigaction *, struct sigaction *)); + int _EXFUN(sigaddset, (sigset_t *, const int)); +diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/stat.h ./newlib/libc/include/sys/stat.h +--- ../newlib-1.11.0.orig/newlib/libc/include/sys/stat.h Sat Feb 23 15:46:28 2002 ++++ ./newlib/libc/include/sys/stat.h Tue Nov 25 09:41:35 2003 +@@ -127,7 +127,7 @@ + int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); + mode_t _EXFUN(umask,( mode_t __mask )); + +-#if defined(__rtems__) || defined(__CYGWIN__) ++#if defined(__rtems__) || defined(__CYGWIN__) || 1 + int _EXFUN(lstat,( const char *__path, struct stat *__buf )); + int _EXFUN(mknod,( const char *__path, mode_t __mode, dev_t __dev )); + #endif +diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/unistd.h ./newlib/libc/include/sys/unistd.h +--- ../newlib-1.11.0.orig/newlib/libc/include/sys/unistd.h Sun Aug 18 02:08:39 2002 ++++ ./newlib/libc/include/sys/unistd.h Tue Nov 25 09:46:58 2003 +@@ -158,9 +158,9 @@ + #endif + char * _EXFUN(mktemp, (char *)); + int _EXFUN(sync, (void)); ++#endif + int _EXFUN(readlink, (const char *__path, char *__buf, int __buflen)); + int _EXFUN(symlink, (const char *__name1, const char *__name2)); +-#endif + + #define F_OK 0 + #define R_OK 4 +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.am ./newlib/libc/sys/mipsunknown/Makefile.am +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.am Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/Makefile.am Mon Nov 24 21:04:11 2003 +@@ -0,0 +1,14 @@ ++## Process this file with automake to generate Makefile.in ++ ++AUTOMAKE_OPTIONS = cygnus ++ ++INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) ++ ++noinst_LIBRARIES = lib.a ++ ++lib_a_SOURCES = syscalls.c ++ ++all: crt0.o ++ ++ACLOCAL_AMFLAGS = -I ../../.. ++CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.in ./newlib/libc/sys/mipsunknown/Makefile.in +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.in Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/Makefile.in Mon Nov 24 21:04:22 2003 +@@ -0,0 +1,329 @@ ++# Makefile.in generated automatically by automake 1.4 from Makefile.am ++ ++# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++ ++SHELL = @SHELL@ ++ ++srcdir = @srcdir@ ++top_srcdir = @top_srcdir@ ++VPATH = @srcdir@ ++prefix = @prefix@ ++exec_prefix = @exec_prefix@ ++ ++bindir = @bindir@ ++sbindir = @sbindir@ ++libexecdir = @libexecdir@ ++datadir = @datadir@ ++sysconfdir = @sysconfdir@ ++sharedstatedir = @sharedstatedir@ ++localstatedir = @localstatedir@ ++libdir = @libdir@ ++infodir = @infodir@ ++mandir = @mandir@ ++includedir = @includedir@ ++oldincludedir = /usr/include ++ ++DESTDIR = ++ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++ ++top_builddir = . ++ ++ACLOCAL = @ACLOCAL@ ++AUTOCONF = @AUTOCONF@ ++AUTOMAKE = @AUTOMAKE@ ++AUTOHEADER = @AUTOHEADER@ ++ ++INSTALL = @INSTALL@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++transform = @program_transform_name@ ++ ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_alias = @build_alias@ ++build_triplet = @build@ ++host_alias = @host_alias@ ++host_triplet = @host@ ++target_alias = @target_alias@ ++target_triplet = @target@ ++AR = @AR@ ++AS = @AS@ ++CC = @CC@ ++CPP = @CPP@ ++EXEEXT = @EXEEXT@ ++LDFLAGS = @LDFLAGS@ ++MAINT = @MAINT@ ++MAKEINFO = @MAKEINFO@ ++NEWLIB_CFLAGS = @NEWLIB_CFLAGS@ ++OBJEXT = @OBJEXT@ ++PACKAGE = @PACKAGE@ ++RANLIB = @RANLIB@ ++VERSION = @VERSION@ ++aext = @aext@ ++libm_machine_dir = @libm_machine_dir@ ++machine_dir = @machine_dir@ ++newlib_basedir = @newlib_basedir@ ++oext = @oext@ ++sys_dir = @sys_dir@ ++ ++AUTOMAKE_OPTIONS = cygnus ++ ++INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) ++ ++noinst_LIBRARIES = lib.a ++ ++lib_a_SOURCES = syscalls.c ++ ++ACLOCAL_AMFLAGS = -I ../../.. ++CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs ++CONFIG_CLEAN_FILES = ++LIBRARIES = $(noinst_LIBRARIES) ++ ++ ++DEFS = @DEFS@ -I. -I$(srcdir) ++CPPFLAGS = @CPPFLAGS@ ++LIBS = @LIBS@ ++lib_a_LIBADD = ++lib_a_OBJECTS = syscalls.o ++CFLAGS = @CFLAGS@ ++COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++CCLD = $(CC) ++LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ ++DIST_COMMON = Makefile.am Makefile.in aclocal.m4 configure configure.in ++ ++ ++DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) ++ ++TAR = gnutar ++GZIP_ENV = --best ++SOURCES = $(lib_a_SOURCES) ++OBJECTS = $(lib_a_OBJECTS) ++ ++all: all-redirect ++.SUFFIXES: ++.SUFFIXES: .S .c .o .s ++$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) ++ cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile ++ ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ cd $(top_builddir) \ ++ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status ++ ++$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in \ ++ ../../../acinclude.m4 ../../../aclocal.m4 \ ++ ../../../libtool.m4 ++ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) ++ ++config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ $(SHELL) ./config.status --recheck ++$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) ++ cd $(srcdir) && $(AUTOCONF) ++ ++mostlyclean-noinstLIBRARIES: ++ ++clean-noinstLIBRARIES: ++ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) ++ ++distclean-noinstLIBRARIES: ++ ++maintainer-clean-noinstLIBRARIES: ++ ++.c.o: ++ $(COMPILE) -c $< ++ ++.s.o: ++ $(COMPILE) -c $< ++ ++.S.o: ++ $(COMPILE) -c $< ++ ++mostlyclean-compile: ++ -rm -f *.o core *.core ++ ++clean-compile: ++ ++distclean-compile: ++ -rm -f *.tab.c ++ ++maintainer-clean-compile: ++ ++lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES) ++ -rm -f lib.a ++ $(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD) ++ $(RANLIB) lib.a ++ ++tags: TAGS ++ ++ID: $(HEADERS) $(SOURCES) $(LISP) ++ list='$(SOURCES) $(HEADERS)'; \ ++ unique=`for i in $$list; do echo $$i; done | \ ++ awk ' { files[$$0] = 1; } \ ++ END { for (i in files) print i; }'`; \ ++ here=`pwd` && cd $(srcdir) \ ++ && mkid -f$$here/ID $$unique $(LISP) ++ ++TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) ++ tags=; \ ++ here=`pwd`; \ ++ list='$(SOURCES) $(HEADERS)'; \ ++ unique=`for i in $$list; do echo $$i; done | \ ++ awk ' { files[$$0] = 1; } \ ++ END { for (i in files) print i; }'`; \ ++ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ ++ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) ++ ++mostlyclean-tags: ++ ++clean-tags: ++ ++distclean-tags: ++ -rm -f TAGS ID ++ ++maintainer-clean-tags: ++ ++distdir = $(PACKAGE)-$(VERSION) ++top_distdir = $(distdir) ++ ++# This target untars the dist file and tries a VPATH configuration. Then ++# it guarantees that the distribution is self-contained by making another ++# tarfile. ++distcheck: dist ++ -rm -rf $(distdir) ++ GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz ++ mkdir $(distdir)/=build ++ mkdir $(distdir)/=inst ++ dc_install_base=`cd $(distdir)/=inst && pwd`; \ ++ cd $(distdir)/=build \ ++ && ../configure --srcdir=.. --prefix=$$dc_install_base \ ++ && $(MAKE) $(AM_MAKEFLAGS) \ ++ && $(MAKE) $(AM_MAKEFLAGS) dvi \ ++ && $(MAKE) $(AM_MAKEFLAGS) check \ ++ && $(MAKE) $(AM_MAKEFLAGS) install \ ++ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ ++ && $(MAKE) $(AM_MAKEFLAGS) dist ++ -rm -rf $(distdir) ++ @banner="$(distdir).tar.gz is ready for distribution"; \ ++ dashes=`echo "$$banner" | sed s/./=/g`; \ ++ echo "$$dashes"; \ ++ echo "$$banner"; \ ++ echo "$$dashes" ++dist: distdir ++ -chmod -R a+r $(distdir) ++ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) ++ -rm -rf $(distdir) ++dist-all: distdir ++ -chmod -R a+r $(distdir) ++ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) ++ -rm -rf $(distdir) ++distdir: $(DISTFILES) ++ -rm -rf $(distdir) ++ mkdir $(distdir) ++ -chmod 777 $(distdir) ++ @for file in $(DISTFILES); do \ ++ if test -f $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ cp -pr $$/$$file $(distdir)/$$file; \ ++ else \ ++ test -f $(distdir)/$$file \ ++ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ ++ || cp -p $$d/$$file $(distdir)/$$file || :; \ ++ fi; \ ++ done ++info-am: ++info: info-am ++dvi-am: ++dvi: dvi-am ++check-am: ++check: check-am ++installcheck-am: ++installcheck: installcheck-am ++install-info-am: ++install-info: install-info-am ++install-exec-am: ++install-exec: install-exec-am ++ ++install-data-am: ++install-data: install-data-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++install: install-am ++uninstall-am: ++uninstall: uninstall-am ++all-am: Makefile $(LIBRARIES) ++all-redirect: all-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install ++installdirs: ++ ++ ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -rm -f Makefile $(CONFIG_CLEAN_FILES) ++ -rm -f config.cache config.log stamp-h stamp-h[0-9]* ++ ++maintainer-clean-generic: ++mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ ++ mostlyclean-tags mostlyclean-generic ++ ++mostlyclean: mostlyclean-am ++ ++clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ ++ mostlyclean-am ++ ++clean: clean-am ++ ++distclean-am: distclean-noinstLIBRARIES distclean-compile \ ++ distclean-tags distclean-generic clean-am ++ ++distclean: distclean-am ++ -rm -f config.status ++ ++maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ ++ maintainer-clean-compile maintainer-clean-tags \ ++ maintainer-clean-generic distclean-am ++ @echo "This command is intended for maintainers to use;" ++ @echo "it deletes files that may require special tools to rebuild." ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f config.status ++ ++.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ ++clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ ++mostlyclean-compile distclean-compile clean-compile \ ++maintainer-clean-compile tags mostlyclean-tags distclean-tags \ ++clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ ++check-am installcheck-am installcheck install-info-am install-info \ ++install-exec-am install-exec install-data-am install-data install-am \ ++install uninstall-am uninstall all-redirect all-am all installdirs \ ++mostlyclean-generic distclean-generic clean-generic \ ++maintainer-clean-generic clean mostlyclean distclean maintainer-clean ++ ++ ++all: crt0.o ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/aclocal.m4 ./newlib/libc/sys/mipsunknown/aclocal.m4 +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/aclocal.m4 Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/aclocal.m4 Mon Nov 24 20:40:47 2003 +@@ -0,0 +1,324 @@ ++dnl aclocal.m4 generated automatically by aclocal 1.4 ++ ++dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. ++dnl This file is free software; the Free Software Foundation ++dnl gives unlimited permission to copy and/or distribute it, ++dnl with or without modifications, as long as this notice is preserved. ++ ++dnl This program is distributed in the hope that it will be useful, ++dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++dnl PARTICULAR PURPOSE. ++ ++dnl This provides configure definitions used by all the newlib ++dnl configure.in files. ++ ++dnl Basic newlib configury. This calls basic introductory stuff, ++dnl including AM_INIT_AUTOMAKE and AC_CANONICAL_HOST. It also runs ++dnl configure.host. The only argument is the relative path to the top ++dnl newlib directory. ++ ++AC_DEFUN(NEWLIB_CONFIGURE, ++[ ++dnl Default to --enable-multilib ++AC_ARG_ENABLE(multilib, ++[ --enable-multilib build many library versions (default)], ++[case "${enableval}" in ++ yes) multilib=yes ;; ++ no) multilib=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;; ++ esac], [multilib=yes])dnl ++ ++dnl Support --enable-target-optspace ++AC_ARG_ENABLE(target-optspace, ++[ --enable-target-optspace optimize for space], ++[case "${enableval}" in ++ yes) target_optspace=yes ;; ++ no) target_optspace=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for target-optspace option) ;; ++ esac], [target_optspace=])dnl ++ ++dnl Support --enable-malloc-debugging - currently only supported for Cygwin ++AC_ARG_ENABLE(malloc-debugging, ++[ --enable-malloc-debugging indicate malloc debugging requested], ++[case "${enableval}" in ++ yes) malloc_debugging=yes ;; ++ no) malloc_debugging=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for malloc-debugging option) ;; ++ esac], [malloc_debugging=])dnl ++ ++dnl Support --enable-newlib-mb ++AC_ARG_ENABLE(newlib-mb, ++[ --enable-newlib-mb enable multibyte support], ++[case "${enableval}" in ++ yes) newlib_mb=yes ;; ++ no) newlib_mb=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for newlib-mb option) ;; ++ esac], [newlib_mb=])dnl ++ ++dnl Support --enable-newlib-multithread ++AC_ARG_ENABLE(newlib-multithread, ++[ --enable-newlib-multithread enable support for multiple threads], ++[case "${enableval}" in ++ yes) newlib_multithread=yes ;; ++ no) newlib_multithread=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for newlib-multithread option) ;; ++ esac], [newlib_multithread=yes])dnl ++ ++dnl Support --enable-newlib-elix-level ++AC_ARG_ENABLE(newlib-elix-level, ++[ --enable-newlib-elix-level supply desired elix library level (1-4)], ++[case "${enableval}" in ++ 0) newlib_elix_level=0 ;; ++ 1) newlib_elix_level=1 ;; ++ 2) newlib_elix_level=2 ;; ++ 3) newlib_elix_level=3 ;; ++ 4) newlib_elix_level=4 ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for newlib-elix-level option) ;; ++ esac], [newlib_elix_level=0])dnl ++ ++dnl Support --disable-newlib-io-float ++AC_ARG_ENABLE(newlib-io-float, ++[ --disable-newlib-io-float disable printf/scanf family float support], ++[case "${enableval}" in ++ yes) newlib_io_float=yes ;; ++ no) newlib_io_float=no ;; ++ *) AC_MSG_ERROR(bad value ${enableval} for newlib-io-float option) ;; ++ esac], [newlib_io_float=yes])dnl ++ ++ ++dnl We may get other options which we don't document: ++dnl --with-target-subdir, --with-multisrctop, --with-multisubdir ++ ++test -z "[$]{with_target_subdir}" && with_target_subdir=. ++ ++if test "[$]{srcdir}" = "."; then ++ if test "[$]{with_target_subdir}" != "."; then ++ newlib_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1" ++ else ++ newlib_basedir="[$]{srcdir}/[$]{with_multisrctop}$1" ++ fi ++else ++ newlib_basedir="[$]{srcdir}/$1" ++fi ++AC_SUBST(newlib_basedir) ++ ++AC_CANONICAL_SYSTEM ++ ++AM_INIT_AUTOMAKE(newlib, 1.11.0) ++ ++# FIXME: We temporarily define our own version of AC_PROG_CC. This is ++# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We ++# are probably using a cross compiler, which will not be able to fully ++# link an executable. This should really be fixed in autoconf ++# itself. ++ ++AC_DEFUN(LIB_AC_PROG_CC, ++[AC_BEFORE([$0], [AC_PROG_CPP])dnl ++AC_CHECK_PROG(CC, gcc, gcc) ++if test -z "$CC"; then ++ AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc) ++ test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) ++fi ++ ++AC_PROG_CC_GNU ++ ++if test $ac_cv_prog_gcc = yes; then ++ GCC=yes ++dnl Check whether -g works, even if CFLAGS is set, in case the package ++dnl plays around with CFLAGS (such as to build both debugging and ++dnl normal versions of a library), tasteless as that idea is. ++ ac_test_CFLAGS="${CFLAGS+set}" ++ ac_save_CFLAGS="$CFLAGS" ++ CFLAGS= ++ AC_PROG_CC_G ++ if test "$ac_test_CFLAGS" = set; then ++ CFLAGS="$ac_save_CFLAGS" ++ elif test $ac_cv_prog_cc_g = yes; then ++ CFLAGS="-g -O2" ++ else ++ CFLAGS="-O2" ++ fi ++else ++ GCC= ++ test "${CFLAGS+set}" = set || CFLAGS="-g" ++fi ++]) ++ ++LIB_AC_PROG_CC ++ ++AC_CHECK_TOOL(AS, as) ++AC_CHECK_TOOL(AR, ar) ++AC_CHECK_TOOL(RANLIB, ranlib, :) ++ ++AC_PROG_INSTALL ++ ++AM_MAINTAINER_MODE ++ ++# We need AC_EXEEXT to keep automake happy in cygnus mode. However, ++# at least currently, we never actually build a program, so we never ++# need to use $(EXEEXT). Moreover, the test for EXEEXT normally ++# fails, because we are probably configuring with a cross compiler ++# which can't create executables. So we include AC_EXEEXT to keep ++# automake happy, but we don't execute it, since we don't care about ++# the result. ++if false; then ++ AC_EXEEXT ++fi ++ ++. [$]{newlib_basedir}/configure.host ++ ++newlib_cflags="[$]{newlib_cflags} -fno-builtin" ++ ++NEWLIB_CFLAGS=${newlib_cflags} ++AC_SUBST(NEWLIB_CFLAGS) ++ ++LDFLAGS=${ldflags} ++AC_SUBST(LDFLAGS) ++ ++AM_CONDITIONAL(ELIX_LEVEL_0, test x[$]{newlib_elix_level} = x0) ++AM_CONDITIONAL(ELIX_LEVEL_1, test x[$]{newlib_elix_level} = x1) ++AM_CONDITIONAL(ELIX_LEVEL_2, test x[$]{newlib_elix_level} = x2) ++AM_CONDITIONAL(ELIX_LEVEL_3, test x[$]{newlib_elix_level} = x3) ++AM_CONDITIONAL(ELIX_LEVEL_4, test x[$]{newlib_elix_level} = x4) ++ ++AM_CONDITIONAL(USE_LIBTOOL, test x[$]{use_libtool} = xyes) ++ ++# Hard-code OBJEXT. Normally it is set by AC_OBJEXT, but we ++# use oext, which is set in configure.host based on the target platform. ++OBJEXT=${oext} ++ ++AC_SUBST(OBJEXT) ++AC_SUBST(oext) ++AC_SUBST(aext) ++ ++AC_SUBST(libm_machine_dir) ++AC_SUBST(machine_dir) ++AC_SUBST(sys_dir) ++]) ++ ++# Do all the work for Automake. This macro actually does too much -- ++# some checks are only needed if your package does certain things. ++# But this isn't really a big deal. ++ ++# serial 1 ++ ++dnl Usage: ++dnl AM_INIT_AUTOMAKE(package,version, [no-define]) ++ ++AC_DEFUN(AM_INIT_AUTOMAKE, ++[AC_REQUIRE([AC_PROG_INSTALL]) ++PACKAGE=[$1] ++AC_SUBST(PACKAGE) ++VERSION=[$2] ++AC_SUBST(VERSION) ++dnl test to see if srcdir already configured ++if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then ++ AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) ++fi ++ifelse([$3],, ++AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) ++AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) ++AC_REQUIRE([AM_SANITY_CHECK]) ++AC_REQUIRE([AC_ARG_PROGRAM]) ++dnl FIXME This is truly gross. ++missing_dir=`cd $ac_aux_dir && pwd` ++AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) ++AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) ++AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) ++AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) ++AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) ++AC_REQUIRE([AC_PROG_MAKE_SET])]) ++ ++# ++# Check to make sure that the build environment is sane. ++# ++ ++AC_DEFUN(AM_SANITY_CHECK, ++[AC_MSG_CHECKING([whether build environment is sane]) ++# Just in case ++sleep 1 ++echo timestamp > conftestfile ++# Do `set' in a subshell so we don't clobber the current shell's ++# arguments. Must try -L first in case configure is actually a ++# symlink; some systems play weird games with the mod time of symlinks ++# (eg FreeBSD returns the mod time of the symlink's containing ++# directory). ++if ( ++ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` ++ if test "[$]*" = "X"; then ++ # -L didn't work. ++ set X `ls -t $srcdir/configure conftestfile` ++ fi ++ if test "[$]*" != "X $srcdir/configure conftestfile" \ ++ && test "[$]*" != "X conftestfile $srcdir/configure"; then ++ ++ # If neither matched, then we have a broken ls. This can happen ++ # if, for instance, CONFIG_SHELL is bash and it inherits a ++ # broken ls alias from the environment. This has actually ++ # happened. Such a system could not be considered "sane". ++ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken ++alias in your environment]) ++ fi ++ ++ test "[$]2" = conftestfile ++ ) ++then ++ # Ok. ++ : ++else ++ AC_MSG_ERROR([newly created file is older than distributed files! ++Check your system clock]) ++fi ++rm -f conftest* ++AC_MSG_RESULT(yes)]) ++ ++dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) ++dnl The program must properly implement --version. ++AC_DEFUN(AM_MISSING_PROG, ++[AC_MSG_CHECKING(for working $2) ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if ($2 --version) < /dev/null > /dev/null 2>&1; then ++ $1=$2 ++ AC_MSG_RESULT(found) ++else ++ $1="$3/missing $2" ++ AC_MSG_RESULT(missing) ++fi ++AC_SUBST($1)]) ++ ++# Add --enable-maintainer-mode option to configure. ++# From Jim Meyering ++ ++# serial 1 ++ ++AC_DEFUN(AM_MAINTAINER_MODE, ++[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) ++ dnl maintainer-mode is disabled by default ++ AC_ARG_ENABLE(maintainer-mode, ++[ --enable-maintainer-mode enable make rules and dependencies not useful ++ (and sometimes confusing) to the casual installer], ++ USE_MAINTAINER_MODE=$enableval, ++ USE_MAINTAINER_MODE=no) ++ AC_MSG_RESULT($USE_MAINTAINER_MODE) ++ AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) ++ MAINT=$MAINTAINER_MODE_TRUE ++ AC_SUBST(MAINT)dnl ++] ++) ++ ++# Define a conditional. ++ ++AC_DEFUN(AM_CONDITIONAL, ++[AC_SUBST($1_TRUE) ++AC_SUBST($1_FALSE) ++if $2; then ++ $1_TRUE= ++ $1_FALSE='#' ++else ++ $1_TRUE='#' ++ $1_FALSE= ++fi]) ++ +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure ./newlib/libc/sys/mipsunknown/configure +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/configure Mon Nov 24 20:43:05 2003 +@@ -0,0 +1,1863 @@ ++#! /bin/sh ++ ++# Guess values for system-dependent variables and create Makefiles. ++# Generated automatically using autoconf version 2.13 ++# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. ++# ++# This configure script is free software; the Free Software Foundation ++# gives unlimited permission to copy, distribute and modify it. ++ ++# Defaults: ++ac_help= ++ac_default_prefix=/usr/local ++# Any additions from configure.in: ++ac_help="$ac_help ++ --enable-multilib build many library versions (default)" ++ac_help="$ac_help ++ --enable-target-optspace optimize for space" ++ac_help="$ac_help ++ --enable-malloc-debugging indicate malloc debugging requested" ++ac_help="$ac_help ++ --enable-newlib-mb enable multibyte support" ++ac_help="$ac_help ++ --enable-newlib-multithread enable support for multiple threads" ++ac_help="$ac_help ++ --enable-newlib-elix-level supply desired elix library level (1-4)" ++ac_help="$ac_help ++ --disable-newlib-io-float disable printf/scanf family float support" ++ac_help="$ac_help ++ --enable-maintainer-mode enable make rules and dependencies not useful ++ (and sometimes confusing) to the casual installer" ++ ++# Initialize some variables set by options. ++# The variables have the same names as the options, with ++# dashes changed to underlines. ++build=NONE ++cache_file=./config.cache ++exec_prefix=NONE ++host=NONE ++no_create= ++nonopt=NONE ++no_recursion= ++prefix=NONE ++program_prefix=NONE ++program_suffix=NONE ++program_transform_name=s,x,x, ++silent= ++site= ++sitefile= ++srcdir= ++target=NONE ++verbose= ++x_includes=NONE ++x_libraries=NONE ++bindir='${exec_prefix}/bin' ++sbindir='${exec_prefix}/sbin' ++libexecdir='${exec_prefix}/libexec' ++datadir='${prefix}/share' ++sysconfdir='${prefix}/etc' ++sharedstatedir='${prefix}/com' ++localstatedir='${prefix}/var' ++libdir='${exec_prefix}/lib' ++includedir='${prefix}/include' ++oldincludedir='/usr/include' ++infodir='${prefix}/info' ++mandir='${prefix}/man' ++ ++# Initialize some other variables. ++subdirs= ++MFLAGS= MAKEFLAGS= ++SHELL=${CONFIG_SHELL-/bin/sh} ++# Maximum number of lines to put in a shell here document. ++ac_max_here_lines=12 ++ ++ac_prev= ++for ac_option ++do ++ ++ # If the previous option needs an argument, assign it. ++ if test -n "$ac_prev"; then ++ eval "$ac_prev=\$ac_option" ++ ac_prev= ++ continue ++ fi ++ ++ case "$ac_option" in ++ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; ++ *) ac_optarg= ;; ++ esac ++ ++ # Accept the important Cygnus configure options, so we can diagnose typos. ++ ++ case "$ac_option" in ++ ++ -bindir | --bindir | --bindi | --bind | --bin | --bi) ++ ac_prev=bindir ;; ++ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) ++ bindir="$ac_optarg" ;; ++ ++ -build | --build | --buil | --bui | --bu) ++ ac_prev=build ;; ++ -build=* | --build=* | --buil=* | --bui=* | --bu=*) ++ build="$ac_optarg" ;; ++ ++ -cache-file | --cache-file | --cache-fil | --cache-fi \ ++ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ++ ac_prev=cache_file ;; ++ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ ++ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) ++ cache_file="$ac_optarg" ;; ++ ++ -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ++ ac_prev=datadir ;; ++ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ ++ | --da=*) ++ datadir="$ac_optarg" ;; ++ ++ -disable-* | --disable-*) ++ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` ++ # Reject names that are not valid shell variable names. ++ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then ++ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } ++ fi ++ ac_feature=`echo $ac_feature| sed 's/-/_/g'` ++ eval "enable_${ac_feature}=no" ;; ++ ++ -enable-* | --enable-*) ++ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` ++ # Reject names that are not valid shell variable names. ++ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then ++ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } ++ fi ++ ac_feature=`echo $ac_feature| sed 's/-/_/g'` ++ case "$ac_option" in ++ *=*) ;; ++ *) ac_optarg=yes ;; ++ esac ++ eval "enable_${ac_feature}='$ac_optarg'" ;; ++ ++ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ ++ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ ++ | --exec | --exe | --ex) ++ ac_prev=exec_prefix ;; ++ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ ++ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ ++ | --exec=* | --exe=* | --ex=*) ++ exec_prefix="$ac_optarg" ;; ++ ++ -gas | --gas | --ga | --g) ++ # Obsolete; use --with-gas. ++ with_gas=yes ;; ++ ++ -help | --help | --hel | --he) ++ # Omit some internal or obsolete options to make the list less imposing. ++ # This message is too long to be a string in the A/UX 3.1 sh. ++ cat << EOF ++Usage: configure [options] [host] ++Options: [defaults in brackets after descriptions] ++Configuration: ++ --cache-file=FILE cache test results in FILE ++ --help print this message ++ --no-create do not create output files ++ --quiet, --silent do not print \`checking...' messages ++ --site-file=FILE use FILE as the site file ++ --version print the version of autoconf that created configure ++Directory and file names: ++ --prefix=PREFIX install architecture-independent files in PREFIX ++ [$ac_default_prefix] ++ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX ++ [same as prefix] ++ --bindir=DIR user executables in DIR [EPREFIX/bin] ++ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] ++ --libexecdir=DIR program executables in DIR [EPREFIX/libexec] ++ --datadir=DIR read-only architecture-independent data in DIR ++ [PREFIX/share] ++ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] ++ --sharedstatedir=DIR modifiable architecture-independent data in DIR ++ [PREFIX/com] ++ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] ++ --libdir=DIR object code libraries in DIR [EPREFIX/lib] ++ --includedir=DIR C header files in DIR [PREFIX/include] ++ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] ++ --infodir=DIR info documentation in DIR [PREFIX/info] ++ --mandir=DIR man documentation in DIR [PREFIX/man] ++ --srcdir=DIR find the sources in DIR [configure dir or ..] ++ --program-prefix=PREFIX prepend PREFIX to installed program names ++ --program-suffix=SUFFIX append SUFFIX to installed program names ++ --program-transform-name=PROGRAM ++ run sed PROGRAM on installed program names ++EOF ++ cat << EOF ++Host type: ++ --build=BUILD configure for building on BUILD [BUILD=HOST] ++ --host=HOST configure for HOST [guessed] ++ --target=TARGET configure for TARGET [TARGET=HOST] ++Features and packages: ++ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) ++ --enable-FEATURE[=ARG] include FEATURE [ARG=yes] ++ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] ++ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) ++ --x-includes=DIR X include files are in DIR ++ --x-libraries=DIR X library files are in DIR ++EOF ++ if test -n "$ac_help"; then ++ echo "--enable and --with options recognized:$ac_help" ++ fi ++ exit 0 ;; ++ ++ -host | --host | --hos | --ho) ++ ac_prev=host ;; ++ -host=* | --host=* | --hos=* | --ho=*) ++ host="$ac_optarg" ;; ++ ++ -includedir | --includedir | --includedi | --included | --include \ ++ | --includ | --inclu | --incl | --inc) ++ ac_prev=includedir ;; ++ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ ++ | --includ=* | --inclu=* | --incl=* | --inc=*) ++ includedir="$ac_optarg" ;; ++ ++ -infodir | --infodir | --infodi | --infod | --info | --inf) ++ ac_prev=infodir ;; ++ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) ++ infodir="$ac_optarg" ;; ++ ++ -libdir | --libdir | --libdi | --libd) ++ ac_prev=libdir ;; ++ -libdir=* | --libdir=* | --libdi=* | --libd=*) ++ libdir="$ac_optarg" ;; ++ ++ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ ++ | --libexe | --libex | --libe) ++ ac_prev=libexecdir ;; ++ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ ++ | --libexe=* | --libex=* | --libe=*) ++ libexecdir="$ac_optarg" ;; ++ ++ -localstatedir | --localstatedir | --localstatedi | --localstated \ ++ | --localstate | --localstat | --localsta | --localst \ ++ | --locals | --local | --loca | --loc | --lo) ++ ac_prev=localstatedir ;; ++ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ ++ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ ++ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) ++ localstatedir="$ac_optarg" ;; ++ ++ -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ++ ac_prev=mandir ;; ++ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) ++ mandir="$ac_optarg" ;; ++ ++ -nfp | --nfp | --nf) ++ # Obsolete; use --without-fp. ++ with_fp=no ;; ++ ++ -no-create | --no-create | --no-creat | --no-crea | --no-cre \ ++ | --no-cr | --no-c) ++ no_create=yes ;; ++ ++ -no-recursion | --no-recursion | --no-recursio | --no-recursi \ ++ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ++ no_recursion=yes ;; ++ ++ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ ++ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ ++ | --oldin | --oldi | --old | --ol | --o) ++ ac_prev=oldincludedir ;; ++ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ ++ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ ++ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) ++ oldincludedir="$ac_optarg" ;; ++ ++ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ++ ac_prev=prefix ;; ++ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ++ prefix="$ac_optarg" ;; ++ ++ -program-prefix | --program-prefix | --program-prefi | --program-pref \ ++ | --program-pre | --program-pr | --program-p) ++ ac_prev=program_prefix ;; ++ -program-prefix=* | --program-prefix=* | --program-prefi=* \ ++ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) ++ program_prefix="$ac_optarg" ;; ++ ++ -program-suffix | --program-suffix | --program-suffi | --program-suff \ ++ | --program-suf | --program-su | --program-s) ++ ac_prev=program_suffix ;; ++ -program-suffix=* | --program-suffix=* | --program-suffi=* \ ++ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) ++ program_suffix="$ac_optarg" ;; ++ ++ -program-transform-name | --program-transform-name \ ++ | --program-transform-nam | --program-transform-na \ ++ | --program-transform-n | --program-transform- \ ++ | --program-transform | --program-transfor \ ++ | --program-transfo | --program-transf \ ++ | --program-trans | --program-tran \ ++ | --progr-tra | --program-tr | --program-t) ++ ac_prev=program_transform_name ;; ++ -program-transform-name=* | --program-transform-name=* \ ++ | --program-transform-nam=* | --program-transform-na=* \ ++ | --program-transform-n=* | --program-transform-=* \ ++ | --program-transform=* | --program-transfor=* \ ++ | --program-transfo=* | --program-transf=* \ ++ | --program-trans=* | --program-tran=* \ ++ | --progr-tra=* | --program-tr=* | --program-t=*) ++ program_transform_name="$ac_optarg" ;; ++ ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil) ++ silent=yes ;; ++ ++ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ++ ac_prev=sbindir ;; ++ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ ++ | --sbi=* | --sb=*) ++ sbindir="$ac_optarg" ;; ++ ++ -sharedstatedir | --sharedstatedir | --sharedstatedi \ ++ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ ++ | --sharedst | --shareds | --shared | --share | --shar \ ++ | --sha | --sh) ++ ac_prev=sharedstatedir ;; ++ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ ++ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ ++ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ ++ | --sha=* | --sh=*) ++ sharedstatedir="$ac_optarg" ;; ++ ++ -site | --site | --sit) ++ ac_prev=site ;; ++ -site=* | --site=* | --sit=*) ++ site="$ac_optarg" ;; ++ ++ -site-file | --site-file | --site-fil | --site-fi | --site-f) ++ ac_prev=sitefile ;; ++ -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*) ++ sitefile="$ac_optarg" ;; ++ ++ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ++ ac_prev=srcdir ;; ++ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ++ srcdir="$ac_optarg" ;; ++ ++ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ ++ | --syscon | --sysco | --sysc | --sys | --sy) ++ ac_prev=sysconfdir ;; ++ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ ++ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) ++ sysconfdir="$ac_optarg" ;; ++ ++ -target | --target | --targe | --targ | --tar | --ta | --t) ++ ac_prev=target ;; ++ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) ++ target="$ac_optarg" ;; ++ ++ -v | -verbose | --verbose | --verbos | --verbo | --verb) ++ verbose=yes ;; ++ ++ -version | --version | --versio | --versi | --vers) ++ echo "configure generated by autoconf version 2.13" ++ exit 0 ;; ++ ++ -with-* | --with-*) ++ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` ++ # Reject names that are not valid shell variable names. ++ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then ++ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } ++ fi ++ ac_package=`echo $ac_package| sed 's/-/_/g'` ++ case "$ac_option" in ++ *=*) ;; ++ *) ac_optarg=yes ;; ++ esac ++ eval "with_${ac_package}='$ac_optarg'" ;; ++ ++ -without-* | --without-*) ++ ac_package=`echo $ac_option|sed -e 's/-*without-//'` ++ # Reject names that are not valid shell variable names. ++ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then ++ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } ++ fi ++ ac_package=`echo $ac_package| sed 's/-/_/g'` ++ eval "with_${ac_package}=no" ;; ++ ++ --x) ++ # Obsolete; use --with-x. ++ with_x=yes ;; ++ ++ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ ++ | --x-incl | --x-inc | --x-in | --x-i) ++ ac_prev=x_includes ;; ++ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ ++ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) ++ x_includes="$ac_optarg" ;; ++ ++ -x-libraries | --x-libraries | --x-librarie | --x-librari \ ++ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ++ ac_prev=x_libraries ;; ++ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ ++ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) ++ x_libraries="$ac_optarg" ;; ++ ++ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ++ ;; ++ ++ *) ++ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then ++ echo "configure: warning: $ac_option: invalid host type" 1>&2 ++ fi ++ if test "x$nonopt" != xNONE; then ++ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ++ fi ++ nonopt="$ac_option" ++ ;; ++ ++ esac ++done ++ ++if test -n "$ac_prev"; then ++ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } ++fi ++ ++trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 ++ ++# File descriptor usage: ++# 0 standard input ++# 1 file creation ++# 2 errors and warnings ++# 3 some systems may open it to /dev/tty ++# 4 used on the Kubota Titan ++# 6 checking for... messages and results ++# 5 compiler messages saved in config.log ++if test "$silent" = yes; then ++ exec 6>/dev/null ++else ++ exec 6>&1 ++fi ++exec 5>./config.log ++ ++echo "\ ++This file contains any messages produced by compilers while ++running configure, to aid debugging if configure makes a mistake. ++" 1>&5 ++ ++# Strip out --no-create and --no-recursion so they do not pile up. ++# Also quote any args containing shell metacharacters. ++ac_configure_args= ++for ac_arg ++do ++ case "$ac_arg" in ++ -no-create | --no-create | --no-creat | --no-crea | --no-cre \ ++ | --no-cr | --no-c) ;; ++ -no-recursion | --no-recursion | --no-recursio | --no-recursi \ ++ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; ++ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ++ ac_configure_args="$ac_configure_args '$ac_arg'" ;; ++ *) ac_configure_args="$ac_configure_args $ac_arg" ;; ++ esac ++done ++ ++# NLS nuisances. ++# Only set these to C if already set. These must not be set unconditionally ++# because not all systems understand e.g. LANG=C (notably SCO). ++# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! ++# Non-C LC_CTYPE values break the ctype check. ++if test "${LANG+set}" = set; then LANG=C; export LANG; fi ++if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi ++if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi ++if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi ++ ++# confdefs.h avoids OS command line length limits that DEFS can exceed. ++rm -rf conftest* confdefs.h ++# AIX cpp loses on an empty file, so make sure it contains at least a newline. ++echo > confdefs.h ++ ++# A filename unique to this package, relative to the directory that ++# configure is in, which we can look for to find out if srcdir is correct. ++ac_unique_file=syscalls.c ++ ++# Find the source files, if location was not specified. ++if test -z "$srcdir"; then ++ ac_srcdir_defaulted=yes ++ # Try the directory containing this script, then its parent. ++ ac_prog=$0 ++ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` ++ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. ++ srcdir=$ac_confdir ++ if test ! -r $srcdir/$ac_unique_file; then ++ srcdir=.. ++ fi ++else ++ ac_srcdir_defaulted=no ++fi ++if test ! -r $srcdir/$ac_unique_file; then ++ if test "$ac_srcdir_defaulted" = yes; then ++ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } ++ else ++ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } ++ fi ++fi ++srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` ++ ++# Prefer explicitly selected file to automatically selected ones. ++if test -z "$sitefile"; then ++ if test -z "$CONFIG_SITE"; then ++ if test "x$prefix" != xNONE; then ++ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" ++ else ++ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" ++ fi ++ fi ++else ++ CONFIG_SITE="$sitefile" ++fi ++for ac_site_file in $CONFIG_SITE; do ++ if test -r "$ac_site_file"; then ++ echo "loading site script $ac_site_file" ++ . "$ac_site_file" ++ fi ++done ++ ++if test -r "$cache_file"; then ++ echo "loading cache $cache_file" ++ . $cache_file ++else ++ echo "creating cache $cache_file" ++ > $cache_file ++fi ++ ++ac_ext=c ++# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ++ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' ++cross_compiling=$ac_cv_prog_cc_cross ++ ++ac_exeext= ++ac_objext=o ++if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then ++ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. ++ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ++ ac_n= ac_c=' ++' ac_t=' ' ++ else ++ ac_n=-n ac_c= ac_t= ++ fi ++else ++ ac_n= ac_c='\c' ac_t= ++fi ++ ++ ++ ++ac_aux_dir= ++for ac_dir in ../../../.. $srcdir/../../../..; do ++ if test -f $ac_dir/install-sh; then ++ ac_aux_dir=$ac_dir ++ ac_install_sh="$ac_aux_dir/install-sh -c" ++ break ++ elif test -f $ac_dir/install.sh; then ++ ac_aux_dir=$ac_dir ++ ac_install_sh="$ac_aux_dir/install.sh -c" ++ break ++ fi ++done ++if test -z "$ac_aux_dir"; then ++ { echo "configure: error: can not find install-sh or install.sh in ../../../.. $srcdir/../../../.." 1>&2; exit 1; } ++fi ++ac_config_guess=$ac_aux_dir/config.guess ++ac_config_sub=$ac_aux_dir/config.sub ++ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. ++ ++ ++# Find a good install program. We prefer a C program (faster), ++# so one script is as good as another. But avoid the broken or ++# incompatible versions: ++# SysV /etc/install, /usr/sbin/install ++# SunOS /usr/etc/install ++# IRIX /sbin/install ++# AIX /bin/install ++# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag ++# AFS /usr/afsws/bin/install, which mishandles nonexistent args ++# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" ++# ./install, which can be erroneously created by make from ./install.sh. ++echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ++echo "configure:586: checking for a BSD compatible install" >&5 ++if test -z "$INSTALL"; then ++if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" ++ for ac_dir in $PATH; do ++ # Account for people who put trailing slashes in PATH elements. ++ case "$ac_dir/" in ++ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; ++ *) ++ # OSF1 and SCO ODT 3.0 have their own names for install. ++ # Don't use installbsd from OSF since it installs stuff as root ++ # by default. ++ for ac_prog in ginstall scoinst install; do ++ if test -f $ac_dir/$ac_prog; then ++ if test $ac_prog = install && ++ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then ++ # AIX install. It has an incompatible calling convention. ++ : ++ else ++ ac_cv_path_install="$ac_dir/$ac_prog -c" ++ break 2 ++ fi ++ fi ++ done ++ ;; ++ esac ++ done ++ IFS="$ac_save_IFS" ++ ++fi ++ if test "${ac_cv_path_install+set}" = set; then ++ INSTALL="$ac_cv_path_install" ++ else ++ # As a last resort, use the slow shell script. We don't cache a ++ # path for INSTALL within a source directory, because that will ++ # break other packages using the cache if that directory is ++ # removed, or if the path is relative. ++ INSTALL="$ac_install_sh" ++ fi ++fi ++echo "$ac_t""$INSTALL" 1>&6 ++ ++# Use test -z because SunOS4 sh mishandles braces in ${var-val}. ++# It thinks the first close brace ends the variable substitution. ++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' ++ ++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' ++ ++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ++ ++echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 ++echo "configure:639: checking whether build environment is sane" >&5 ++# Just in case ++sleep 1 ++echo timestamp > conftestfile ++# Do `set' in a subshell so we don't clobber the current shell's ++# arguments. Must try -L first in case configure is actually a ++# symlink; some systems play weird games with the mod time of symlinks ++# (eg FreeBSD returns the mod time of the symlink's containing ++# directory). ++if ( ++ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` ++ if test "$*" = "X"; then ++ # -L didn't work. ++ set X `ls -t $srcdir/configure conftestfile` ++ fi ++ if test "$*" != "X $srcdir/configure conftestfile" \ ++ && test "$*" != "X conftestfile $srcdir/configure"; then ++ ++ # If neither matched, then we have a broken ls. This can happen ++ # if, for instance, CONFIG_SHELL is bash and it inherits a ++ # broken ls alias from the environment. This has actually ++ # happened. Such a system could not be considered "sane". ++ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken ++alias in your environment" 1>&2; exit 1; } ++ fi ++ ++ test "$2" = conftestfile ++ ) ++then ++ # Ok. ++ : ++else ++ { echo "configure: error: newly created file is older than distributed files! ++Check your system clock" 1>&2; exit 1; } ++fi ++rm -f conftest* ++echo "$ac_t""yes" 1>&6 ++if test "$program_transform_name" = s,x,x,; then ++ program_transform_name= ++else ++ # Double any \ or $. echo might interpret backslashes. ++ cat <<\EOF_SED > conftestsed ++s,\\,\\\\,g; s,\$,$$,g ++EOF_SED ++ program_transform_name="`echo $program_transform_name|sed -f conftestsed`" ++ rm -f conftestsed ++fi ++test "$program_prefix" != NONE && ++ program_transform_name="s,^,${program_prefix},; $program_transform_name" ++# Use a double $ so make ignores it. ++test "$program_suffix" != NONE && ++ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" ++ ++# sed with no file args requires a program. ++test "$program_transform_name" = "" && program_transform_name="s,x,x," ++ ++echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 ++echo "configure:696: checking whether ${MAKE-make} sets \${MAKE}" >&5 ++set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` ++if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ cat > conftestmake <<\EOF ++all: ++ @echo 'ac_maketemp="${MAKE}"' ++EOF ++# GNU make sometimes prints "make[1]: Entering...", which would confuse us. ++eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` ++if test -n "$ac_maketemp"; then ++ eval ac_cv_prog_make_${ac_make}_set=yes ++else ++ eval ac_cv_prog_make_${ac_make}_set=no ++fi ++rm -f conftestmake ++fi ++if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then ++ echo "$ac_t""yes" 1>&6 ++ SET_MAKE= ++else ++ echo "$ac_t""no" 1>&6 ++ SET_MAKE="MAKE=${MAKE-make}" ++fi ++ ++if test $host != $build; then ++ ac_tool_prefix=${host_alias}- ++else ++ ac_tool_prefix= ++fi ++ ++echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 ++echo "configure:729: checking for Cygwin environment" >&5 ++if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then ++ rm -rf conftest* ++ ac_cv_cygwin=yes ++else ++ echo "configure: failed program was:" >&5 ++ cat conftest.$ac_ext >&5 ++ rm -rf conftest* ++ ac_cv_cygwin=no ++fi ++rm -f conftest* ++rm -f conftest* ++fi ++ ++echo "$ac_t""$ac_cv_cygwin" 1>&6 ++CYGWIN= ++test "$ac_cv_cygwin" = yes && CYGWIN=yes ++echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 ++echo "configure:762: checking for mingw32 environment" >&5 ++if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then ++ rm -rf conftest* ++ ac_cv_mingw32=yes ++else ++ echo "configure: failed program was:" >&5 ++ cat conftest.$ac_ext >&5 ++ rm -rf conftest* ++ ac_cv_mingw32=no ++fi ++rm -f conftest* ++rm -f conftest* ++fi ++ ++echo "$ac_t""$ac_cv_mingw32" 1>&6 ++MINGW32= ++test "$ac_cv_mingw32" = yes && MINGW32=yes ++ ++# Check whether --enable-multilib or --disable-multilib was given. ++if test "${enable_multilib+set}" = set; then ++ enableval="$enable_multilib" ++ case "${enableval}" in ++ yes) multilib=yes ;; ++ no) multilib=no ;; ++ *) { echo "configure: error: bad value ${enableval} for multilib option" 1>&2; exit 1; } ;; ++ esac ++else ++ multilib=yes ++fi ++ ++# Check whether --enable-target-optspace or --disable-target-optspace was given. ++if test "${enable_target_optspace+set}" = set; then ++ enableval="$enable_target_optspace" ++ case "${enableval}" in ++ yes) target_optspace=yes ;; ++ no) target_optspace=no ;; ++ *) { echo "configure: error: bad value ${enableval} for target-optspace option" 1>&2; exit 1; } ;; ++ esac ++else ++ target_optspace= ++fi ++ ++# Check whether --enable-malloc-debugging or --disable-malloc-debugging was given. ++if test "${enable_malloc_debugging+set}" = set; then ++ enableval="$enable_malloc_debugging" ++ case "${enableval}" in ++ yes) malloc_debugging=yes ;; ++ no) malloc_debugging=no ;; ++ *) { echo "configure: error: bad value ${enableval} for malloc-debugging option" 1>&2; exit 1; } ;; ++ esac ++else ++ malloc_debugging= ++fi ++ ++# Check whether --enable-newlib-mb or --disable-newlib-mb was given. ++if test "${enable_newlib_mb+set}" = set; then ++ enableval="$enable_newlib_mb" ++ case "${enableval}" in ++ yes) newlib_mb=yes ;; ++ no) newlib_mb=no ;; ++ *) { echo "configure: error: bad value ${enableval} for newlib-mb option" 1>&2; exit 1; } ;; ++ esac ++else ++ newlib_mb= ++fi ++ ++# Check whether --enable-newlib-multithread or --disable-newlib-multithread was given. ++if test "${enable_newlib_multithread+set}" = set; then ++ enableval="$enable_newlib_multithread" ++ case "${enableval}" in ++ yes) newlib_multithread=yes ;; ++ no) newlib_multithread=no ;; ++ *) { echo "configure: error: bad value ${enableval} for newlib-multithread option" 1>&2; exit 1; } ;; ++ esac ++else ++ newlib_multithread=yes ++fi ++ ++# Check whether --enable-newlib-elix-level or --disable-newlib-elix-level was given. ++if test "${enable_newlib_elix_level+set}" = set; then ++ enableval="$enable_newlib_elix_level" ++ case "${enableval}" in ++ 0) newlib_elix_level=0 ;; ++ 1) newlib_elix_level=1 ;; ++ 2) newlib_elix_level=2 ;; ++ 3) newlib_elix_level=3 ;; ++ 4) newlib_elix_level=4 ;; ++ *) { echo "configure: error: bad value ${enableval} for newlib-elix-level option" 1>&2; exit 1; } ;; ++ esac ++else ++ newlib_elix_level=0 ++fi ++ ++# Check whether --enable-newlib-io-float or --disable-newlib-io-float was given. ++if test "${enable_newlib_io_float+set}" = set; then ++ enableval="$enable_newlib_io_float" ++ case "${enableval}" in ++ yes) newlib_io_float=yes ;; ++ no) newlib_io_float=no ;; ++ *) { echo "configure: error: bad value ${enableval} for newlib-io-float option" 1>&2; exit 1; } ;; ++ esac ++else ++ newlib_io_float=yes ++fi ++ ++ ++ ++test -z "${with_target_subdir}" && with_target_subdir=. ++ ++if test "${srcdir}" = "."; then ++ if test "${with_target_subdir}" != "."; then ++ newlib_basedir="${srcdir}/${with_multisrctop}../../../.." ++ else ++ newlib_basedir="${srcdir}/${with_multisrctop}../../.." ++ fi ++else ++ newlib_basedir="${srcdir}/../../.." ++fi ++ ++ ++ ++# Do some error checking and defaulting for the host and target type. ++# The inputs are: ++# configure --host=HOST --target=TARGET --build=BUILD NONOPT ++# ++# The rules are: ++# 1. You are not allowed to specify --host, --target, and nonopt at the ++# same time. ++# 2. Host defaults to nonopt. ++# 3. If nonopt is not specified, then host defaults to the current host, ++# as determined by config.guess. ++# 4. Target and build default to nonopt. ++# 5. If nonopt is not specified, then target and build default to host. ++ ++# The aliases save the names the user supplied, while $host etc. ++# will get canonicalized. ++case $host---$target---$nonopt in ++NONE---*---* | *---NONE---* | *---*---NONE) ;; ++*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; ++esac ++ ++ ++# Make sure we can run config.sub. ++if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : ++else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } ++fi ++ ++echo $ac_n "checking host system type""... $ac_c" 1>&6 ++echo "configure:921: checking host system type" >&5 ++ ++host_alias=$host ++case "$host_alias" in ++NONE) ++ case $nonopt in ++ NONE) ++ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : ++ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } ++ fi ;; ++ *) host_alias=$nonopt ;; ++ esac ;; ++esac ++ ++host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` ++host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` ++host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` ++host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` ++echo "$ac_t""$host" 1>&6 ++ ++echo $ac_n "checking target system type""... $ac_c" 1>&6 ++echo "configure:942: checking target system type" >&5 ++ ++target_alias=$target ++case "$target_alias" in ++NONE) ++ case $nonopt in ++ NONE) target_alias=$host_alias ;; ++ *) target_alias=$nonopt ;; ++ esac ;; ++esac ++ ++target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` ++target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` ++target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` ++target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` ++echo "$ac_t""$target" 1>&6 ++ ++echo $ac_n "checking build system type""... $ac_c" 1>&6 ++echo "configure:960: checking build system type" >&5 ++ ++build_alias=$build ++case "$build_alias" in ++NONE) ++ case $nonopt in ++ NONE) build_alias=$host_alias ;; ++ *) build_alias=$nonopt ;; ++ esac ;; ++esac ++ ++build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` ++build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` ++build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` ++build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` ++echo "$ac_t""$build" 1>&6 ++ ++test "$host_alias" != "$target_alias" && ++ test "$program_prefix$program_suffix$program_transform_name" = \ ++ NONENONEs,x,x, && ++ program_prefix=${target_alias}- ++ ++ ++ ++PACKAGE=newlib ++ ++VERSION=1.11.0 ++ ++if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then ++ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } ++fi ++cat >> confdefs.h <> confdefs.h <&6 ++echo "configure:1003: checking for working aclocal" >&5 ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if (aclocal --version) < /dev/null > /dev/null 2>&1; then ++ ACLOCAL=aclocal ++ echo "$ac_t""found" 1>&6 ++else ++ ACLOCAL="$missing_dir/missing aclocal" ++ echo "$ac_t""missing" 1>&6 ++fi ++ ++echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 ++echo "configure:1016: checking for working autoconf" >&5 ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if (autoconf --version) < /dev/null > /dev/null 2>&1; then ++ AUTOCONF=autoconf ++ echo "$ac_t""found" 1>&6 ++else ++ AUTOCONF="$missing_dir/missing autoconf" ++ echo "$ac_t""missing" 1>&6 ++fi ++ ++echo $ac_n "checking for working automake""... $ac_c" 1>&6 ++echo "configure:1029: checking for working automake" >&5 ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if (automake --version) < /dev/null > /dev/null 2>&1; then ++ AUTOMAKE=automake ++ echo "$ac_t""found" 1>&6 ++else ++ AUTOMAKE="$missing_dir/missing automake" ++ echo "$ac_t""missing" 1>&6 ++fi ++ ++echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 ++echo "configure:1042: checking for working autoheader" >&5 ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if (autoheader --version) < /dev/null > /dev/null 2>&1; then ++ AUTOHEADER=autoheader ++ echo "$ac_t""found" 1>&6 ++else ++ AUTOHEADER="$missing_dir/missing autoheader" ++ echo "$ac_t""missing" 1>&6 ++fi ++ ++echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 ++echo "configure:1055: checking for working makeinfo" >&5 ++# Run test in a subshell; some versions of sh will print an error if ++# an executable is not found, even if stderr is redirected. ++# Redirect stdin to placate older versions of autoconf. Sigh. ++if (makeinfo --version) < /dev/null > /dev/null 2>&1; then ++ MAKEINFO=makeinfo ++ echo "$ac_t""found" 1>&6 ++else ++ MAKEINFO="$missing_dir/missing makeinfo" ++ echo "$ac_t""missing" 1>&6 ++fi ++ ++ ++ ++# FIXME: We temporarily define our own version of AC_PROG_CC. This is ++# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We ++# are probably using a cross compiler, which will not be able to fully ++# link an executable. This should really be fixed in autoconf ++# itself. ++ ++ ++ ++# Extract the first word of "gcc", so it can be a program name with args. ++set dummy gcc; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1080: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ ac_cv_prog_CC="gcc" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++fi ++fi ++CC="$ac_cv_prog_CC" ++if test -n "$CC"; then ++ echo "$ac_t""$CC" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++if test -z "$CC"; then ++ # Extract the first word of "cc", so it can be a program name with args. ++set dummy cc; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1110: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_prog_rejected=no ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ++ ac_prog_rejected=yes ++ continue ++ fi ++ ac_cv_prog_CC="cc" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++if test $ac_prog_rejected = yes; then ++ # We found a bogon in the path, so make sure we never use it. ++ set dummy $ac_cv_prog_CC ++ shift ++ if test $# -gt 0; then ++ # We chose a different compiler from the bogus one. ++ # However, it has the same basename, so the bogon will be chosen ++ # first if we set CC to just the basename; use the full file name. ++ shift ++ set dummy "$ac_dir/$ac_word" "$@" ++ shift ++ ac_cv_prog_CC="$@" ++ fi ++fi ++fi ++fi ++CC="$ac_cv_prog_CC" ++if test -n "$CC"; then ++ echo "$ac_t""$CC" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } ++fi ++ ++echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 ++echo "configure:1159: checking whether we are using GNU C" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ++ ac_cv_prog_gcc=yes ++else ++ ac_cv_prog_gcc=no ++fi ++fi ++ ++echo "$ac_t""$ac_cv_prog_gcc" 1>&6 ++ ++if test $ac_cv_prog_gcc = yes; then ++ GCC=yes ++ ac_test_CFLAGS="${CFLAGS+set}" ++ ac_save_CFLAGS="$CFLAGS" ++ CFLAGS= ++ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 ++echo "configure:1183: checking whether ${CC-cc} accepts -g" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ echo 'void f(){}' > conftest.c ++if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ++ ac_cv_prog_cc_g=yes ++else ++ ac_cv_prog_cc_g=no ++fi ++rm -f conftest* ++ ++fi ++ ++echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 ++ if test "$ac_test_CFLAGS" = set; then ++ CFLAGS="$ac_save_CFLAGS" ++ elif test $ac_cv_prog_cc_g = yes; then ++ CFLAGS="-g -O2" ++ else ++ CFLAGS="-O2" ++ fi ++else ++ GCC= ++ test "${CFLAGS+set}" = set || CFLAGS="-g" ++fi ++ ++ ++# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. ++set dummy ${ac_tool_prefix}as; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1214: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$AS"; then ++ ac_cv_prog_AS="$AS" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ ac_cv_prog_AS="${ac_tool_prefix}as" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++ test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="as" ++fi ++fi ++AS="$ac_cv_prog_AS" ++if test -n "$AS"; then ++ echo "$ac_t""$AS" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++ ++ ++# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. ++set dummy ${ac_tool_prefix}ar; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1246: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$AR"; then ++ ac_cv_prog_AR="$AR" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ ac_cv_prog_AR="${ac_tool_prefix}ar" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" ++fi ++fi ++AR="$ac_cv_prog_AR" ++if test -n "$AR"; then ++ echo "$ac_t""$AR" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++ ++ ++# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. ++set dummy ${ac_tool_prefix}ranlib; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1278: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$RANLIB"; then ++ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++fi ++fi ++RANLIB="$ac_cv_prog_RANLIB" ++if test -n "$RANLIB"; then ++ echo "$ac_t""$RANLIB" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++ ++if test -z "$ac_cv_prog_RANLIB"; then ++if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "ranlib", so it can be a program name with args. ++set dummy ranlib; ac_word=$2 ++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ++echo "configure:1310: checking for $ac_word" >&5 ++if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test -n "$RANLIB"; then ++ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. ++else ++ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ++ ac_dummy="$PATH" ++ for ac_dir in $ac_dummy; do ++ test -z "$ac_dir" && ac_dir=. ++ if test -f $ac_dir/$ac_word; then ++ ac_cv_prog_RANLIB="ranlib" ++ break ++ fi ++ done ++ IFS="$ac_save_ifs" ++ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" ++fi ++fi ++RANLIB="$ac_cv_prog_RANLIB" ++if test -n "$RANLIB"; then ++ echo "$ac_t""$RANLIB" 1>&6 ++else ++ echo "$ac_t""no" 1>&6 ++fi ++ ++else ++ RANLIB=":" ++fi ++fi ++ ++ ++# Find a good install program. We prefer a C program (faster), ++# so one script is as good as another. But avoid the broken or ++# incompatible versions: ++# SysV /etc/install, /usr/sbin/install ++# SunOS /usr/etc/install ++# IRIX /sbin/install ++# AIX /bin/install ++# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag ++# AFS /usr/afsws/bin/install, which mishandles nonexistent args ++# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" ++# ./install, which can be erroneously created by make from ./install.sh. ++echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ++echo "configure:1355: checking for a BSD compatible install" >&5 ++if test -z "$INSTALL"; then ++if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" ++ for ac_dir in $PATH; do ++ # Account for people who put trailing slashes in PATH elements. ++ case "$ac_dir/" in ++ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; ++ *) ++ # OSF1 and SCO ODT 3.0 have their own names for install. ++ # Don't use installbsd from OSF since it installs stuff as root ++ # by default. ++ for ac_prog in ginstall scoinst install; do ++ if test -f $ac_dir/$ac_prog; then ++ if test $ac_prog = install && ++ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then ++ # AIX install. It has an incompatible calling convention. ++ : ++ else ++ ac_cv_path_install="$ac_dir/$ac_prog -c" ++ break 2 ++ fi ++ fi ++ done ++ ;; ++ esac ++ done ++ IFS="$ac_save_IFS" ++ ++fi ++ if test "${ac_cv_path_install+set}" = set; then ++ INSTALL="$ac_cv_path_install" ++ else ++ # As a last resort, use the slow shell script. We don't cache a ++ # path for INSTALL within a source directory, because that will ++ # break other packages using the cache if that directory is ++ # removed, or if the path is relative. ++ INSTALL="$ac_install_sh" ++ fi ++fi ++echo "$ac_t""$INSTALL" 1>&6 ++ ++# Use test -z because SunOS4 sh mishandles braces in ${var-val}. ++# It thinks the first close brace ends the variable substitution. ++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' ++ ++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' ++ ++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' ++ ++ ++echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 ++echo "configure:1409: checking whether to enable maintainer-specific portions of Makefiles" >&5 ++ # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. ++if test "${enable_maintainer_mode+set}" = set; then ++ enableval="$enable_maintainer_mode" ++ USE_MAINTAINER_MODE=$enableval ++else ++ USE_MAINTAINER_MODE=no ++fi ++ ++ echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 ++ ++ ++if test $USE_MAINTAINER_MODE = yes; then ++ MAINTAINER_MODE_TRUE= ++ MAINTAINER_MODE_FALSE='#' ++else ++ MAINTAINER_MODE_TRUE='#' ++ MAINTAINER_MODE_FALSE= ++fi ++ MAINT=$MAINTAINER_MODE_TRUE ++ ++ ++ ++# We need AC_EXEEXT to keep automake happy in cygnus mode. However, ++# at least currently, we never actually build a program, so we never ++# need to use $(EXEEXT). Moreover, the test for EXEEXT normally ++# fails, because we are probably configuring with a cross compiler ++# which can't create executables. So we include AC_EXEEXT to keep ++# automake happy, but we don't execute it, since we don't care about ++# the result. ++if false; then ++ ++ ++echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 ++echo "configure:1443: checking for executable suffix" >&5 ++if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then ++ echo $ac_n "(cached) $ac_c" 1>&6 ++else ++ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then ++ ac_cv_exeext=.exe ++else ++ rm -f conftest* ++ echo 'int main () { return 0; }' > conftest.$ac_ext ++ ac_cv_exeext= ++ if { (eval echo configure:1453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then ++ for file in conftest.*; do ++ case $file in ++ *.c | *.o | *.obj | *.ilk | *.pdb) ;; ++ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; ++ esac ++ done ++ else ++ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } ++ fi ++ rm -f conftest* ++ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no ++fi ++fi ++ ++EXEEXT="" ++test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} ++echo "$ac_t""${ac_cv_exeext}" 1>&6 ++ac_exeext=$EXEEXT ++ ++fi ++ ++. ${newlib_basedir}/configure.host ++ ++newlib_cflags="${newlib_cflags} -fno-builtin" ++ ++NEWLIB_CFLAGS=${newlib_cflags} ++ ++ ++LDFLAGS=${ldflags} ++ ++ ++ ++ ++if test x${newlib_elix_level} = x0; then ++ ELIX_LEVEL_0_TRUE= ++ ELIX_LEVEL_0_FALSE='#' ++else ++ ELIX_LEVEL_0_TRUE='#' ++ ELIX_LEVEL_0_FALSE= ++fi ++ ++ ++if test x${newlib_elix_level} = x1; then ++ ELIX_LEVEL_1_TRUE= ++ ELIX_LEVEL_1_FALSE='#' ++else ++ ELIX_LEVEL_1_TRUE='#' ++ ELIX_LEVEL_1_FALSE= ++fi ++ ++ ++if test x${newlib_elix_level} = x2; then ++ ELIX_LEVEL_2_TRUE= ++ ELIX_LEVEL_2_FALSE='#' ++else ++ ELIX_LEVEL_2_TRUE='#' ++ ELIX_LEVEL_2_FALSE= ++fi ++ ++ ++if test x${newlib_elix_level} = x3; then ++ ELIX_LEVEL_3_TRUE= ++ ELIX_LEVEL_3_FALSE='#' ++else ++ ELIX_LEVEL_3_TRUE='#' ++ ELIX_LEVEL_3_FALSE= ++fi ++ ++ ++if test x${newlib_elix_level} = x4; then ++ ELIX_LEVEL_4_TRUE= ++ ELIX_LEVEL_4_FALSE='#' ++else ++ ELIX_LEVEL_4_TRUE='#' ++ ELIX_LEVEL_4_FALSE= ++fi ++ ++ ++ ++if test x${use_libtool} = xyes; then ++ USE_LIBTOOL_TRUE= ++ USE_LIBTOOL_FALSE='#' ++else ++ USE_LIBTOOL_TRUE='#' ++ USE_LIBTOOL_FALSE= ++fi ++ ++# Hard-code OBJEXT. Normally it is set by AC_OBJEXT, but we ++# use oext, which is set in configure.host based on the target platform. ++OBJEXT=${oext} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++trap '' 1 2 15 ++cat > confcache <<\EOF ++# This file is a shell script that caches the results of configure ++# tests run on this system so they can be shared between configure ++# scripts and configure runs. It is not useful on other systems. ++# If it contains results you don't want to keep, you may remove or edit it. ++# ++# By default, configure uses ./config.cache as the cache file, ++# creating it if it does not exist already. You can give configure ++# the --cache-file=FILE option to use a different cache file; that is ++# what configure does when it calls configure scripts in ++# subdirectories, so they share the cache. ++# Giving --cache-file=/dev/null disables caching, for debugging configure. ++# config.status only pays attention to the cache file if you give it the ++# --recheck option to rerun configure. ++# ++EOF ++# The following way of writing the cache mishandles newlines in values, ++# but we know of no workaround that is simple, portable, and efficient. ++# So, don't put newlines in cache variables' values. ++# Ultrix sh set writes to stderr and can't be redirected directly, ++# and sets the high bit in the cache file unless we assign to the vars. ++(set) 2>&1 | ++ case `(ac_space=' '; set | grep ac_space) 2>&1` in ++ *ac_space=\ *) ++ # `set' does not quote correctly, so add quotes (double-quote substitution ++ # turns \\\\ into \\, and sed turns \\ into \). ++ sed -n \ ++ -e "s/'/'\\\\''/g" \ ++ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ++ ;; ++ *) ++ # `set' quotes correctly as required by POSIX, so do not add quotes. ++ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ++ ;; ++ esac >> confcache ++if cmp -s $cache_file confcache; then ++ : ++else ++ if test -w $cache_file; then ++ echo "updating cache $cache_file" ++ cat confcache > $cache_file ++ else ++ echo "not updating unwritable cache $cache_file" ++ fi ++fi ++rm -f confcache ++ ++trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 ++ ++test "x$prefix" = xNONE && prefix=$ac_default_prefix ++# Let make expand exec_prefix. ++test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ++ ++# Any assignment to VPATH causes Sun make to only execute ++# the first set of double-colon rules, so remove it if not needed. ++# If there is a colon in the path, we need to keep it. ++if test "x$srcdir" = x.; then ++ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' ++fi ++ ++trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 ++ ++# Transform confdefs.h into DEFS. ++# Protect against shell expansion while executing Makefile rules. ++# Protect against Makefile macro expansion. ++cat > conftest.defs <<\EOF ++s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g ++s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g ++s%\[%\\&%g ++s%\]%\\&%g ++s%\$%$$%g ++EOF ++DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` ++rm -f conftest.defs ++ ++ ++# Without the "./", some shells look in PATH for config.status. ++: ${CONFIG_STATUS=./config.status} ++ ++echo creating $CONFIG_STATUS ++rm -f $CONFIG_STATUS ++cat > $CONFIG_STATUS </dev/null | sed 1q`: ++# ++# $0 $ac_configure_args ++# ++# Compiler output produced by configure, useful for debugging ++# configure, is in ./config.log if it exists. ++ ++ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" ++for ac_option ++do ++ case "\$ac_option" in ++ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ++ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" ++ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; ++ -version | --version | --versio | --versi | --vers | --ver | --ve | --v) ++ echo "$CONFIG_STATUS generated by autoconf version 2.13" ++ exit 0 ;; ++ -help | --help | --hel | --he | --h) ++ echo "\$ac_cs_usage"; exit 0 ;; ++ *) echo "\$ac_cs_usage"; exit 1 ;; ++ esac ++done ++ ++ac_given_srcdir=$srcdir ++ac_given_INSTALL="$INSTALL" ++ ++trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 ++EOF ++cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF ++$ac_vpsub ++$extrasub ++s%@SHELL@%$SHELL%g ++s%@CFLAGS@%$CFLAGS%g ++s%@CPPFLAGS@%$CPPFLAGS%g ++s%@CXXFLAGS@%$CXXFLAGS%g ++s%@FFLAGS@%$FFLAGS%g ++s%@DEFS@%$DEFS%g ++s%@LDFLAGS@%$LDFLAGS%g ++s%@LIBS@%$LIBS%g ++s%@exec_prefix@%$exec_prefix%g ++s%@prefix@%$prefix%g ++s%@program_transform_name@%$program_transform_name%g ++s%@bindir@%$bindir%g ++s%@sbindir@%$sbindir%g ++s%@libexecdir@%$libexecdir%g ++s%@datadir@%$datadir%g ++s%@sysconfdir@%$sysconfdir%g ++s%@sharedstatedir@%$sharedstatedir%g ++s%@localstatedir@%$localstatedir%g ++s%@libdir@%$libdir%g ++s%@includedir@%$includedir%g ++s%@oldincludedir@%$oldincludedir%g ++s%@infodir@%$infodir%g ++s%@mandir@%$mandir%g ++s%@newlib_basedir@%$newlib_basedir%g ++s%@host@%$host%g ++s%@host_alias@%$host_alias%g ++s%@host_cpu@%$host_cpu%g ++s%@host_vendor@%$host_vendor%g ++s%@host_os@%$host_os%g ++s%@target@%$target%g ++s%@target_alias@%$target_alias%g ++s%@target_cpu@%$target_cpu%g ++s%@target_vendor@%$target_vendor%g ++s%@target_os@%$target_os%g ++s%@build@%$build%g ++s%@build_alias@%$build_alias%g ++s%@build_cpu@%$build_cpu%g ++s%@build_vendor@%$build_vendor%g ++s%@build_os@%$build_os%g ++s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g ++s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g ++s%@INSTALL_DATA@%$INSTALL_DATA%g ++s%@PACKAGE@%$PACKAGE%g ++s%@VERSION@%$VERSION%g ++s%@ACLOCAL@%$ACLOCAL%g ++s%@AUTOCONF@%$AUTOCONF%g ++s%@AUTOMAKE@%$AUTOMAKE%g ++s%@AUTOHEADER@%$AUTOHEADER%g ++s%@MAKEINFO@%$MAKEINFO%g ++s%@SET_MAKE@%$SET_MAKE%g ++s%@CC@%$CC%g ++s%@AS@%$AS%g ++s%@AR@%$AR%g ++s%@RANLIB@%$RANLIB%g ++s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g ++s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g ++s%@MAINT@%$MAINT%g ++s%@EXEEXT@%$EXEEXT%g ++s%@NEWLIB_CFLAGS@%$NEWLIB_CFLAGS%g ++s%@ELIX_LEVEL_0_TRUE@%$ELIX_LEVEL_0_TRUE%g ++s%@ELIX_LEVEL_0_FALSE@%$ELIX_LEVEL_0_FALSE%g ++s%@ELIX_LEVEL_1_TRUE@%$ELIX_LEVEL_1_TRUE%g ++s%@ELIX_LEVEL_1_FALSE@%$ELIX_LEVEL_1_FALSE%g ++s%@ELIX_LEVEL_2_TRUE@%$ELIX_LEVEL_2_TRUE%g ++s%@ELIX_LEVEL_2_FALSE@%$ELIX_LEVEL_2_FALSE%g ++s%@ELIX_LEVEL_3_TRUE@%$ELIX_LEVEL_3_TRUE%g ++s%@ELIX_LEVEL_3_FALSE@%$ELIX_LEVEL_3_FALSE%g ++s%@ELIX_LEVEL_4_TRUE@%$ELIX_LEVEL_4_TRUE%g ++s%@ELIX_LEVEL_4_FALSE@%$ELIX_LEVEL_4_FALSE%g ++s%@USE_LIBTOOL_TRUE@%$USE_LIBTOOL_TRUE%g ++s%@USE_LIBTOOL_FALSE@%$USE_LIBTOOL_FALSE%g ++s%@OBJEXT@%$OBJEXT%g ++s%@oext@%$oext%g ++s%@aext@%$aext%g ++s%@libm_machine_dir@%$libm_machine_dir%g ++s%@machine_dir@%$machine_dir%g ++s%@sys_dir@%$sys_dir%g ++ ++CEOF ++EOF ++ ++cat >> $CONFIG_STATUS <<\EOF ++ ++# Split the substitutions into bite-sized pieces for seds with ++# small command number limits, like on Digital OSF/1 and HP-UX. ++ac_max_sed_cmds=60 # Maximum number of lines to put in a sed script. ++ac_file=1 # Number of current file. ++ac_beg=1 # First line for current file. ++ac_end=$ac_max_sed_cmds # Line after last line for current file. ++ac_more_lines=: ++ac_sed_cmds="" ++while $ac_more_lines; do ++ if test $ac_beg -gt 1; then ++ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file ++ else ++ sed "${ac_end}q" conftest.subs > conftest.s$ac_file ++ fi ++ if test ! -s conftest.s$ac_file; then ++ ac_more_lines=false ++ rm -f conftest.s$ac_file ++ else ++ if test -z "$ac_sed_cmds"; then ++ ac_sed_cmds="sed -f conftest.s$ac_file" ++ else ++ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" ++ fi ++ ac_file=`expr $ac_file + 1` ++ ac_beg=$ac_end ++ ac_end=`expr $ac_end + $ac_max_sed_cmds` ++ fi ++done ++if test -z "$ac_sed_cmds"; then ++ ac_sed_cmds=cat ++fi ++EOF ++ ++cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF ++for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then ++ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". ++ case "$ac_file" in ++ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ++ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; ++ *) ac_file_in="${ac_file}.in" ;; ++ esac ++ ++ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. ++ ++ # Remove last slash and all that follows it. Not all systems have dirname. ++ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` ++ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then ++ # The file is in a subdirectory. ++ test ! -d "$ac_dir" && mkdir "$ac_dir" ++ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" ++ # A "../" for each directory in $ac_dir_suffix. ++ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` ++ else ++ ac_dir_suffix= ac_dots= ++ fi ++ ++ case "$ac_given_srcdir" in ++ .) srcdir=. ++ if test -z "$ac_dots"; then top_srcdir=. ++ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; ++ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; ++ *) # Relative path. ++ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" ++ top_srcdir="$ac_dots$ac_given_srcdir" ;; ++ esac ++ ++ case "$ac_given_INSTALL" in ++ [/$]*) INSTALL="$ac_given_INSTALL" ;; ++ *) INSTALL="$ac_dots$ac_given_INSTALL" ;; ++ esac ++ ++ echo creating "$ac_file" ++ rm -f "$ac_file" ++ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." ++ case "$ac_file" in ++ *Makefile*) ac_comsub="1i\\ ++# $configure_input" ;; ++ *) ac_comsub= ;; ++ esac ++ ++ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` ++ sed -e "$ac_comsub ++s%@configure_input@%$configure_input%g ++s%@srcdir@%$srcdir%g ++s%@top_srcdir@%$top_srcdir%g ++s%@INSTALL@%$INSTALL%g ++" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file ++fi; done ++rm -f conftest.s* ++ ++EOF ++cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF ++ ++exit 0 ++EOF ++chmod +x $CONFIG_STATUS ++rm -fr confdefs* $ac_clean_files ++test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 ++ +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure.in ./newlib/libc/sys/mipsunknown/configure.in +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure.in Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/configure.in Mon Nov 24 20:33:46 2003 +@@ -0,0 +1,12 @@ ++dnl This is the newlib/libc/sys/mipsunknown configure.in file. ++dnl Process this file with autoconf to produce a configure script. ++ ++AC_PREREQ(2.5) ++AC_INIT(syscalls.c) ++ ++dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake. ++AC_CONFIG_AUX_DIR(../../../..) ++ ++NEWLIB_CONFIGURE(../../..) ++ ++AC_OUTPUT(Makefile) +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/crt0.c ./newlib/libc/sys/mipsunknown/crt0.c +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/crt0.c Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/crt0.c Mon Nov 24 21:03:56 2003 +@@ -0,0 +1,7 @@ ++/* This is just here to make the build proccess happy. The real crt0.c is included in the ++ mips2java dist and will replace this after mips2java is installed */ ++ ++extern void puts(const char *s); ++void _start() { ++ puts("Your build is broken... you shouldn't be using the crt0.c in newlib"); ++} +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/dirent.h ./newlib/libc/sys/mipsunknown/sys/dirent.h +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/dirent.h Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/sys/dirent.h Mon Nov 24 22:46:36 2003 +@@ -0,0 +1,24 @@ ++#ifndef _SYS_DIRENT_H ++#define _SYS_DIRENT_H ++ ++#include ++ ++struct dirent { ++ long d_ino; ++ char d_name[1024]; ++}; ++ ++typedef struct { ++ int dd_fd; ++ int dd_pos; ++ struct dirent ent; ++} DIR; ++ ++# define __dirfd(dp) ((dp)->dd_fd) ++ ++DIR *opendir (const char *); ++struct dirent *readdir (DIR *); ++void rewinddir (DIR *); ++int closedir (DIR *); ++ ++#endif +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/utime.h ./newlib/libc/sys/mipsunknown/sys/utime.h +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/utime.h Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/sys/utime.h Tue Nov 25 09:45:17 2003 +@@ -0,0 +1,20 @@ ++#ifndef _SYS_UTIME_H ++#define _SYS_UTIME_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct utimbuf ++{ ++ time_t actime; ++ time_t modtime; ++}; ++ ++extern int utime(const char *file, const struct utimbuf *buf); ++ ++#ifdef __cplusplus ++}; ++#endif ++ ++#endif /* _SYS_UTIME_H */ +diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/syscalls.c ./newlib/libc/sys/mipsunknown/syscalls.c +--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/syscalls.c Wed Dec 31 19:00:00 1969 ++++ ./newlib/libc/sys/mipsunknown/syscalls.c Tue Nov 25 09:33:57 2003 +@@ -0,0 +1,49 @@ ++#include ++#include ++#include ++#include ++#undef errno ++ ++/* These are just connectors for the reent versions */ ++ ++extern int _mkdir_r(struct _reent *ptr, const char *path, mode_t mode); ++int mkdir(const char *path, mode_t mode) { return _mkdir_r(_REENT, path, mode); } ++ ++extern int _utime_r(struct _reent *ptr, const char *file, struct utimbuf *buf); ++int utime(const char *file, const struct utimbuf *buf) { return _utime_r(_REENT,file,buf); } ++ ++extern int _lstat_r(struct _reent *ptr, const char *path, struct stat *sb); ++int lstat(const char *path, struct stat *sb) { return _lstat_r(_REENT,path,sb); } ++ ++extern int _chdir_r(struct _reent *ptr, const char *path); ++int chdir(const char *path) { return _chdir_r(_REENT,path); } ++ ++extern int _pipe_r(struct _reent *ptr, int *filedes); ++int pipe(int *filedes) { return _pipe_r(_REENT,filedes); } ++ ++extern int _dup2_r(struct _reent *ptr, int oldd, int newd); ++int dup2(int oldd,int newd) { return _dup2_r(_REENT,oldd,newd); } ++ ++extern int _waitpid_r(struct _reent *ptr, pid_t pid, int *status, int opts); ++int waitpid(pid_t pid, int *status, int opts) { return _waitpid_r(_REENT,pid,status,opts); } ++ ++extern char* _getcwd_r(struct _reent *ptr, char *buf, size_t size); ++char* getcwd(char *buf, size_t size) { return _getcwd_r(_REENT,buf,size); } ++ ++extern int _symlink_r(struct _reent *ptr, const char *name1, const char *name2); ++int symlink(const char *name1, const char *name2) { return _symlink_r(_REENT,name1,name2); } ++ ++extern int _readlink_r(struct _reent *ptr, const char *path, const char *buf, int bufsize); ++int readlink(const char *path, const char *buf, int bufsize) { return _readlink_r(_REENT,path,buf,bufsize); } ++ ++extern int _chown_r(struct _reent *ptr, const char *path, uid_t uid, gid_t gid); ++int chown(const char *path, uid_t uid, gid_t gid) { return _chown_r(_REENT,path,uid,gid); } ++ ++extern int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid); ++int fchown(int fd, uid_t uid, gid_t gid) { return _fchown_r(_REENT,fd,uid,gid); } ++ ++extern int _chmod_r(struct _reent *ptr, const char *path, mode_t mode); ++int chmod(const char *path, mode_t mode) { return _chmod_r(_REENT,path,mode); } ++ ++extern int _fchmod_r(struct _reent *ptr, int fd, mode_t mode); ++int fchmod(int fd, mode_t mode) { return _fchmod_r(_REENT,fd,mode); } diff --git a/upstream/patches/newlib-tzset.patch b/upstream/patches/newlib-tzset.patch new file mode 100644 index 0000000..bf16fa9 --- /dev/null +++ b/upstream/patches/newlib-tzset.patch @@ -0,0 +1,17 @@ +=================================================================== +RCS file: /cvs/src/src/newlib/libc/time/tzset_r.c,v +retrieving revision 1.2 +retrieving revision 1.3 +diff -u -r1.2 -r1.3 +--- newlib/libc/time/tzset_r.c 2002/08/26 18:56:09 1.2 ++++ snewlib/libc/time/tzset_r.c 2003/06/03 18:42:09 1.3 +@@ -28,7 +28,8 @@ + struct _reent *reent_ptr) + { + char *tzenv; +- int hh, mm, ss, sign, m, w, d, n; ++ unsigned short hh, mm, ss, m, w, d; ++ int sign, n; + int i, ch; + + if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL)