Initial revision
authorcacao <none@none>
Sat, 3 Oct 1998 19:18:05 +0000 (19:18 +0000)
committercacao <none@none>
Sat, 3 Oct 1998 19:18:05 +0000 (19:18 +0000)
133 files changed:
COPYRIGHT [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
alpha/asmpart.c [new file with mode: 0644]
alpha/calling.doc [new file with mode: 0644]
alpha/cray.c [new file with mode: 0644]
alpha/defines.h [new file with mode: 0644]
alpha/disass.c [new file with mode: 0644]
alpha/gen.c [new file with mode: 0644]
alpha/native-math.h [new file with mode: 0644]
alpha/ngen.c [new file with mode: 0644]
alpha/ngen.h [new file with mode: 0644]
alpha/sigcontext.h [new file with mode: 0644]
alpha/threads.h [new file with mode: 0644]
alpha/types.h [new file with mode: 0644]
asmpart.h [new file with mode: 0644]
builtin.c [new file with mode: 0644]
builtin.h [new file with mode: 0644]
callargs.h [new file with mode: 0644]
comp/block.c [new file with mode: 0644]
comp/defines.c [new file with mode: 0644]
comp/local.c [new file with mode: 0644]
comp/mcode.c [new file with mode: 0644]
comp/parse.c [new file with mode: 0644]
comp/pcmd.c [new file with mode: 0644]
comp/reg.c [new file with mode: 0644]
comp/regalloc.c [new file with mode: 0644]
comp/stack.c [new file with mode: 0644]
comp/tools.c [new file with mode: 0644]
comp/var.c [new file with mode: 0644]
compiler.c [new file with mode: 0644]
compiler.h [new file with mode: 0644]
doc/collect.doc [new file with mode: 0644]
doc/gen.doc [new file with mode: 0644]
global.h [new file with mode: 0644]
headers.c [new file with mode: 0644]
loader.c [new file with mode: 0644]
loader.h [new file with mode: 0644]
main.c [new file with mode: 0644]
nat/io.c [new file with mode: 0644]
nat/lang.c [new file with mode: 0644]
nat/util.c [new file with mode: 0644]
native.c [new file with mode: 0644]
native.h [new file with mode: 0644]
ncomp/mcode.c [new file with mode: 0644]
ncomp/nblock.c [new file with mode: 0644]
ncomp/ncomp.h [new file with mode: 0644]
ncomp/ncompdef.h [new file with mode: 0644]
ncomp/nparse.c [new file with mode: 0644]
ncomp/nreg.c [new file with mode: 0644]
ncomp/nstack.c [new file with mode: 0644]
ncomp/ntools.c [new file with mode: 0644]
newcomp.c [new file with mode: 0644]
src/cacao/cacao.c [new file with mode: 0644]
src/cacaoh/headers.c [new file with mode: 0644]
src/mm/memory.c [new file with mode: 0644]
src/mm/memory.h [new file with mode: 0644]
src/native/native.c [new file with mode: 0644]
src/native/native.h [new file with mode: 0644]
src/threads/green/locks.c [new file with mode: 0644]
src/threads/green/locks.h [new file with mode: 0644]
src/threads/green/threadio.c [new file with mode: 0644]
src/threads/green/threadio.h [new file with mode: 0644]
src/threads/green/threads.c [new file with mode: 0644]
src/threads/green/threads.h [new file with mode: 0644]
src/toolbox/chain.c [new file with mode: 0644]
src/toolbox/chain.h [new file with mode: 0644]
src/toolbox/list.c [new file with mode: 0644]
src/toolbox/list.h [new file with mode: 0644]
src/toolbox/tree.c [new file with mode: 0644]
src/toolbox/tree.h [new file with mode: 0644]
src/vm/builtin.c [new file with mode: 0644]
src/vm/builtin.h [new file with mode: 0644]
src/vm/global.h [new file with mode: 0644]
src/vm/jit/asmpart.h [new file with mode: 0644]
src/vm/loader.c [new file with mode: 0644]
src/vm/loader.h [new file with mode: 0644]
src/vm/tables.c [new file with mode: 0644]
src/vm/tables.h [new file with mode: 0644]
tables.c [new file with mode: 0644]
tables.h [new file with mode: 0644]
tests/JavaPerformance.java [new file with mode: 0644]
tests/a.java [new file with mode: 0644]
tests/array.java [new file with mode: 0644]
tests/b.java [new file with mode: 0644]
tests/counter.java [new file with mode: 0644]
tests/extest.java [new file with mode: 0644]
tests/filter.java [new file with mode: 0644]
tests/fintest.java [new file with mode: 0644]
tests/fp.java [new file with mode: 0644]
tests/fptest.java [new file with mode: 0644]
tests/ftest.java [new file with mode: 0644]
tests/hello.java [new file with mode: 0644]
tests/helper.java [new file with mode: 0644]
tests/hi.java [new file with mode: 0644]
tests/intsieve.java [new file with mode: 0644]
tests/jctest.java [new file with mode: 0644]
tests/leaf.java [new file with mode: 0644]
tests/longtest.java [new file with mode: 0644]
tests/main.java [new file with mode: 0644]
tests/mem.java [new file with mode: 0644]
tests/memtest.java [new file with mode: 0644]
tests/n.java [new file with mode: 0644]
tests/nan.java [new file with mode: 0644]
tests/prop.java [new file with mode: 0644]
tests/scribble.java [new file with mode: 0644]
tests/sieve.java [new file with mode: 0644]
tests/sum.java [new file with mode: 0644]
tests/sum2.java [new file with mode: 0644]
tests/suml.java [new file with mode: 0644]
tests/sumlempty.java [new file with mode: 0644]
tests/t.java [new file with mode: 0644]
tests/tst.java [new file with mode: 0644]
tests/x.java [new file with mode: 0644]
threads/Makefile [new file with mode: 0755]
threads/locks.c [new file with mode: 0644]
threads/locks.h [new file with mode: 0644]
threads/notyet.c [new file with mode: 0644]
threads/thread.c [new file with mode: 0644]
threads/thread.h [new file with mode: 0644]
threads/threadio.c [new file with mode: 0644]
threads/threadio.h [new file with mode: 0644]
toolbox/Makefile [new file with mode: 0755]
toolbox/chain.c [new file with mode: 0644]
toolbox/chain.h [new file with mode: 0644]
toolbox/list.c [new file with mode: 0644]
toolbox/list.h [new file with mode: 0644]
toolbox/loging.c [new file with mode: 0644]
toolbox/loging.h [new file with mode: 0644]
toolbox/memory.c [new file with mode: 0644]
toolbox/memory.h [new file with mode: 0644]
toolbox/tree.c [new file with mode: 0644]
toolbox/tree.h [new file with mode: 0644]

diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644 (file)
index 0000000..faa46f3
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,30 @@
+CACAO is currently under development and unfinished. The current version
+is not allowed to be distributed. Copies of CACAO source can be obtained
+from the authors on request for educational and research purposes free
+of charge. We will make available the sources under GNU licences in the
+future when the sources are stable. Commercial licences can be obtained
+via andi@complang.tuwien.ac.at.
+
+                            NO WARRANTY
+
+  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.
+
+  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
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a1bcca4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,159 @@
+################################################################################
+#                    Makefile for the JavaVM - compiler CACAO                  #
+################################################################################
+#
+# Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+#
+# See file COPYRIGHT for information on usage and disclaimer of warranties
+#
+# Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+#          Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+#
+# Last Change: 1997/10/30
+#
+#
+# ATTENTION: This version of the makefile only works with gmake.
+#            This Makefile not only generates object files, but also additional
+#            files needed during compilation:
+#                nativetypes.hh
+#                nativetables.hh
+#            All object files and the *.hh can be deleted savely. They will be
+#            generated automatically.
+#
+################################################################################
+
+##################### generation of the excutable ##############################
+
+# Enabling/disabling thread support
+USE_THREADS = YES
+#USE_THREADS = NO
+
+ifeq ($(USE_THREADS),YES)
+THREAD_OBJ = threads/threads.a
+THREAD_CFLAGS = -DUSE_THREADS -DEXTERNAL_OVERFLOW -DDONT_FREE_FIRST
+else
+THREAD_OBJ =
+THREAD_CFLAGS =
+endif
+
+CC = cc
+#CFLAGS = -g -mieee -Wall $(THREAD_CFLAGS)
+CFLAGS = -mieee -O3 -Wall $(THREAD_CFLAGS)
+
+#CC = cc
+#CFLAGS = -g3 -ieee $(THREAD_CFLAGS)
+#CFLAGS = -O3 -ieee $(THREAD_CFLAGS)
+
+OBJ = main.o tables.o loader.o compiler.o newcomp.o builtin.o asmpart.o \
+    toolbox/toolbox.a native.o $(THREAD_OBJ)
+OBJH = headers.o tables.o loader.o builtin.o toolbox/toolbox.a $(THREAD_OBJ)
+
+cacao: $(OBJ)
+       $(CC) $(CFLAGS) -o cacao $(OBJ) -lm
+cacaoh: $(OBJH)
+       $(CC) $(CFLAGS) -o cacaoh $(OBJH) -lm
+
+main.o: main.c global.h tables.h compiler.h ncomp/ncomp.h loader.h \
+        asmpart.h builtin.h native.h
+
+headers.o:  headers.c global.h tables.h loader.h
+
+loader.o:   loader.c global.h loader.h tables.h native.h asmpart.h
+
+compiler.o: builtin.h compiler.h global.h loader.h tables.h native.h \
+            asmpart.h compiler.c comp/*.c sysdep/gen.c sysdep/disass.c
+
+newcomp.o:  builtin.h ncomp/ncomp.h global.h loader.h tables.h native.h \
+            asmpart.h ncomp/ncompdef.h ncomp/*.c sysdep/ngen.h sysdep/ngen.c sysdep/disass.c
+
+builtin.o: builtin.c global.h loader.h builtin.h tables.h sysdep/native-math.h
+
+native.o: native.c global.h tables.h native.h asmpart.h builtin.h \
+          nativetypes.hh nativetable.hh nat/*.c
+
+tables.o: tables.c global.h tables.h
+
+global.h: sysdep/types.h toolbox/*.h
+       touch global.h
+
+toolbox/toolbox.a: toolbox/*.c toolbox/*.h
+       cd toolbox; make toolbox.a "CFLAGS=$(CFLAGS)" "CC=$(CC)" 
+
+ifeq ($(USE_THREADS),YES)
+threads/threads.a: threads/*.c threads/*.h sysdep/threads.h
+       cd threads; make threads.a "USE_THREADS=$(USE_THREADS)" "CFLAGS=$(CFLAGS)" "CC=$(CC)" 
+endif
+
+asmpart.o: sysdep/asmpart.c
+       rm -f asmpart.s
+       $(CC) -E sysdep/asmpart.c > asmpart.s
+       $(CC) -c -o asmpart.o asmpart.s
+       rm -f asmpart.s
+
+
+########################### support targets ####################################
+
+clean:
+       rm -f *.o cacao cacaoh cacao.tgz nativetable.hh nativetypes.hh \
+             core tst/core
+       cd toolbox; make clean
+       cd threads; make clean
+
+tar:
+       rm -f cacao.tgz cacao.tar
+       tar -cvf cacao.tar Makefile */Makefile README COPYRIGHT tst/*.java \
+           doc/*.doc html/*.html *.[ch] comp/*.[ch] ncomp/*.[ch] alpha/*.doc alpha/*.[ch] \
+           nat/*.[ch] toolbox/*.[ch] threads/*.[ch] # sparc/*.[ch]
+       ls -l cacao.tar
+       gzip -9 cacao.tar
+       mv cacao.tar.gz cacao.tgz
+       ls -l cacao.tgz
+
+
+########################## supported architectures #############################
+
+config-alpha:
+       rm -f sysdep
+       ln -s alpha sysdep
+       rm -f threads/sysdep
+       ln -s ../sysdep threads/sysdep
+       make clean
+
+config-sparc:
+       rm -f sysdep
+       ln -s sparc sysdep
+       rm -f threads/sysdep
+       ln -s ../sysdep threads/sysdep
+       make clean
+
+
+
+##################### generation of NATIVE - header files ######################
+
+nativetypes.hh nativetable.hh : cacaoh
+       ./cacaoh java.lang.Object \
+       java.lang.String \
+       java.lang.Class \
+       java.lang.ClassLoader \
+       java.lang.Compiler \
+       java.lang.Double \
+       java.lang.Float \
+       java.lang.Math \
+       java.lang.Runtime \
+       java.lang.SecurityManager \
+       java.lang.System \
+       java.lang.Thread \
+       java.lang.ThreadGroup \
+       java.lang.Throwable \
+\
+       java.io.File \
+       java.io.FileDescriptor \
+       java.io.FileInputStream \
+       java.io.FileOutputStream \
+       java.io.PrintStream \
+       java.io.RandomAccessFile \
+\
+       java.util.Properties \
+       java.util.Date
+       
+       
\ No newline at end of file
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..aa706cc
--- /dev/null
+++ b/README
@@ -0,0 +1,31 @@
+************************* README for CACAO version 0.15 ************************
+
+The current sources of CACAO version 0.15 are a snapshot during development.
+They will change in the near future and are badly documented. This version
+is not intended for public distribution. It is made available only for
+educational and research purposes.
+
+To use the CACAO sources put the cacao015.tgz file in a newly created
+directory and uncompress it using gzip and extract the files using tar.
+Make sure you have installed gmake. Enter:
+
+make config-alpha
+make
+
+After this you should have a working version of cacao and cacaoh. How to
+invoke cacao and which class library has to be used is described at the
+CACAO home page (http://www.complang.tuwien.ac.at/java/cacao/index.html).
+
+Under Linux this version currently works only using the option -cf.
+If you want to use the Digital Unix C-compiler change the variable $CC
+in the Makefile from gcc to cc.
+
+The Sparc port is unfinished and not working. So typing "make config-sparc"
+makes no sense in the moment. Threads are currently also not supported.
+
+For questions mail me at cacao@complang.tuwien.ac.at, for very urgent
+questions mail me at andi@complang.tuwien.ac.at.
+
+Have fun with CACAO
+
+       Andreas Krall
diff --git a/alpha/asmpart.c b/alpha/asmpart.c
new file mode 100644 (file)
index 0000000..bd565a4
--- /dev/null
@@ -0,0 +1,1125 @@
+/****************************** asmpart.c **************************************
+*                                                                              *
+*   is an assembly language file, but called .c to fake the preprocessor.      *
+*   It contains the Java-C interface functions for Alpha processors.           *
+*                                                                              *
+*   Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst              *
+*                                                                              *
+*   See file COPYRIGHT for information on usage and disclaimer of warranties   *
+*                                                                              *
+*   Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at            *
+*            Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at            *
+*                                                                              *
+*   Last Change: 1997/04/26                                                    *
+*                                                                              *
+*******************************************************************************/
+
+
+#define v0      $0
+
+#define t0      $1
+#define t1      $2
+#define t2      $3
+#define t3      $4
+#define t4      $5
+#define t5      $6
+#define t6      $7
+#define t7      $8
+
+#define        s0      $9
+#define        s1      $10
+#define        s2      $11
+#define        s3      $12
+#define        s4      $13
+#define        s5      $14
+#define        s6      $15
+
+#define a0      $16
+#define a1      $17
+#define a2      $18
+#define a3      $19
+#define a4      $20
+#define a5      $21
+
+#define t8      $22
+#define t9      $23
+#define t10     $24
+#define t11     $25
+#define ra      $26
+#define t12     $27
+
+#define pv      t12
+#define AT      $at
+#define gp      $29
+#define sp      $30
+#define zero    $31
+
+#define itmp1   $25
+#define itmp2   $28
+#define itmp3   $29
+
+#define xptr    itmp1
+#define xpc     itmp2
+
+#define sf0     $f2
+#define sf1     $f3
+#define sf2     $f4
+#define sf3     $f5
+#define sf4     $f6
+#define sf5     $f7
+#define sf6     $f8
+#define sf7     $f9
+
+#define fzero   $f31
+
+
+#define PAL_imb 134
+
+#define offobjarr 24
+#define offarrsize 8
+
+       .text
+       .set    noat
+       .set    noreorder
+
+
+/********************* exported functions and variables ***********************/
+
+       .globl has_no_x_instr_set
+       .globl synchronize_caches
+       .globl asm_calljavamethod
+       .globl asm_call_jit_compiler
+       .globl asm_dumpregistersandcall
+       .globl asm_handle_exception
+       .globl asm_handle_nat_exception
+       .globl asm_signal_exception
+       .globl new_builtin_checkcast
+       .globl new_builtin_checkarraycast
+       .globl new_builtin_aastore
+       .globl new_builtin_monitorenter
+       .globl new_builtin_monitorexit
+       .globl new_builtin_idiv
+       .globl new_builtin_irem
+       .globl new_builtin_ldiv
+       .globl new_builtin_lrem
+       .globl perform_alpha_threadswitch
+       .globl initialize_thread_stack
+       .globl used_stack_top
+
+
+/*************************** imported variables *******************************/
+
+       .globl newcompiler
+
+
+/*************************** imported functions *******************************/
+
+       .globl compiler_compile
+       .globl builtin_monitorexit
+       .globl builtin_throw_exception
+       .globl builtin_trace_exception
+       .globl class_java_lang_Object
+
+/*********************** function has_no_x_instr_set ***************************
+*                                                                              *
+*   determines if the byte support instruction set (21164a and higher)         *
+*   is available.                                                              *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    has_no_x_instr_set
+has_no_x_instr_set:
+
+       .long   0x47e03c20                  # amask   1,$0
+       jmp     zero,(ra)                   # return
+
+       .end    has_no_x_instr_set
+
+
+/********************* function synchronize_caches ****************************/
+
+       .ent    synchronize_caches
+synchronize_caches:
+
+       call_pal PAL_imb                    # synchronise instruction cache
+       jmp     zero,(ra)                   # return
+
+       .end    synchronize_caches
+
+
+/********************* function asm_calljavamethod *****************************
+*                                                                              *
+*   This function calls a Java-method (which possibly needs compilation)       *
+*   with up to 4 parameters.                                                   *
+*                                                                              *
+*   This functions calls the JIT-compiler which eventually translates the      *
+*   method into machine code.                                                  *
+*                                                                              *
+*   An possibly throwed exception will be returned to the caller as function   *
+*   return value, so the java method cannot return a fucntion value (this      *
+*   function usually calls 'main' and '<clinit>' which do not return a         *
+*   function value).                                                           *
+*                                                                              *
+*   C-prototype:                                                               *
+*    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
+*         void *arg1, void *arg2, void *arg3, void *arg4);                     *
+*                                                                              *
+*******************************************************************************/
+
+#define        MethodPointer   -8
+#define        FrameSize       -12
+#define     IsSync          -16
+#define     IsLeaf          -20
+#define     IntSave         -24
+#define     FltSave         -28
+#define     ExTableSize     -32
+#define     ExTableStart    -32
+
+#define     ExEntrySize     -32
+#define     ExStartPC       -8
+#define     ExEndPC         -16
+#define     ExHandlerPC     -24
+#define     ExCatchType     -32
+
+       .ent    asm_calljavamethod
+
+call_name:
+       .ascii  "calljavamethod\0\0"
+
+       .align  3
+       .quad   0                           # catch type all
+       .quad   calljava_xhandler           # end pc
+       .quad   calljava_xhandler           # end pc
+       .quad   asm_calljavamethod          # start pc
+       .long   1                           # extable size
+       .long   0                           # fltsave
+       .long   0                           # intsave
+       .long   0                           # isleaf
+       .long   0                           # IsSync
+       .long   32                          # frame size
+       .quad   0                           # method pointer (pointer to name) @@@@@
+
+asm_calljavamethod:
+
+       ldgp    gp,0(pv)
+       lda     sp,-32(sp)                  # allocate stack space
+       stq     gp,24(sp)                   # save global pointer
+       stq     ra,0(sp)                    # save return address
+
+       stq     $16,16(sp)                  # save method pointer for compiler
+       lda     $0,16(sp)                   # pass pointer to method pointer via $0
+
+       bis     $17,$17,$16                 # pass the remaining parameters
+       bis     $18,$18,$17
+       bis     $19,$19,$18
+       bis     $20,$20,$19
+
+       lda     $28,asm_call_jit_compiler   # fake virtual function call
+       stq     $28,8(sp)                   # store function address
+       bis     sp,sp,$28                   # set method pointer
+
+       ldq     pv,8($28)                   # method call as in Java
+       jmp     ra,(pv)                     # call JIT compiler
+calljava_jit:
+       lda     pv,-64(ra)                  # asm_calljavamethod-calljava_jit(ra) !!!!!!
+
+calljava_return:
+
+       ldq     ra,0(sp)                    # restore return address
+       ldq     gp,24(sp)                   # restore global pointer
+       lda     sp,32(sp)                   # free stack space
+       ldl     $0,newcompiler              # load newcompiler flag
+       subq    $0,1,$0                     # negate for clearing $0
+       beq     $0,calljava_ret             # if newcompiler skip ex copying
+       bis     $1,$1,$0                    # pass exception to caller (C)
+calljava_ret:
+       jmp     zero,(ra)
+
+calljava_xhandler:
+
+       ldq     gp,24(sp)                   # restore global pointer
+       mov     itmp1,a0
+       jsr     ra,builtin_throw_exception
+       ldq     ra,0(sp)                    # restore return address
+       lda     sp,32(sp)                   # free stack space
+       jmp     zero,(ra)
+       .end    asm_calljavamethod
+
+
+/****************** function asm_call_jit_compiler *****************************
+*                                                                              *
+*   invokes the compiler for untranslated JavaVM methods.                      *
+*                                                                              *
+*   Register R0 contains a pointer to the method info structure (prepared      *
+*   by createcompilerstub). Using the return address in R26 and the            *
+*   offset in the LDA instruction or using the value in methodptr R28 the      *
+*   patching address for storing the method address can be computed:           *
+*                                                                              *
+*   method address was either loaded using                                     *
+*   M_LDQ (REG_PV, REG_PV, a)        # invokestatic/special    ($27)           *
+*   M_LDA (REG_PV, REG_RA, low)                                                *
+*   M_LDAH(REG_PV, REG_RA, high)     # optional                                *
+*   or                                                                         *
+*   M_LDQ (REG_PV, REG_METHODPTR, m) # invokevirtual/interface ($28)           *
+*   in the static case the method pointer can be computed using the            *
+*   return address and the lda function following the jmp instruction          *
+*                                                                              *
+*******************************************************************************/
+
+
+       .ent    asm_call_jit_compiler
+asm_call_jit_compiler:
+
+       ldgp    gp,0(pv)
+       ldl     $22,-8(ra)              # load instruction LDQ PV,xxx($yy)
+       srl     $22,16,$22              # shift right register number $yy
+       and     $22,31,$22              # isolate register number
+       subl    $22,28,$22              # test for REG_METHODPTR
+       beq     $22,noregchange       
+       ldl     $22,0(ra)               # load instruction LDA PV,xxx(RA)
+       sll     $22,48,$22
+       sra     $22,48,$22              # isolate offset
+       addq    $22,ra,$28              # compute update address
+       ldl     $22,4(ra)               # load instruction LDAH PV,xxx(PV)
+       srl     $22,16,$22              # isolate instruction code
+       lda     $22,-0x177b($22)        # test for LDAH
+       bne     $22,noregchange       
+       ldl     $22,0(ra)               # load instruction LDA PV,xxx(RA)
+       sll     $22,16,$22              # compute high offset
+       addl    $22,0,$22               # sign extend high offset
+       addq    $22,$28,$28             # compute update address
+noregchange:
+       lda     sp,-14*8(sp)            # reserve stack space
+       stq     $16,0*8(sp)             # save all argument registers
+       stq     $17,1*8(sp)             # they could be used by method
+       stq     $18,2*8(sp)
+       stq     $19,3*8(sp)
+       stq     $20,4*8(sp)
+       stq     $21,5*8(sp)
+       stt     $f16,6*8(sp)
+       stt     $f17,7*8(sp)
+       stt     $f18,8*8(sp)
+       stt     $f19,9*8(sp)
+       stt     $f20,10*8(sp)
+       stt     $f21,11*8(sp)
+       stq     $28,12*8(sp)            # save method pointer
+       stq     ra,13*8(sp)             # save return address
+
+       ldq     $16,0($0)               # pass 'methodinfo' pointer to
+       jsr     ra,compiler_compile     # compiler
+       ldgp    gp,0(ra)
+
+       call_pal PAL_imb                # synchronise instruction cache
+
+       ldq     $16,0*8(sp)             # load argument registers
+       ldq     $17,1*8(sp)
+       ldq     $18,2*8(sp)
+       ldq     $19,3*8(sp)
+       ldq     $20,4*8(sp)
+       ldq     $21,5*8(sp)
+       ldt     $f16,6*8(sp)
+       ldt     $f17,7*8(sp)
+       ldt     $f18,8*8(sp)
+       ldt     $f19,9*8(sp)
+       ldt     $f20,10*8(sp)
+       ldt     $f21,11*8(sp)
+       ldq     $28,12*8(sp)            # load method pointer
+       ldq     ra,13*8(sp)             # load return address
+       lda     sp,14*8(sp)             # deallocate stack area
+
+       ldl     $22,-8(ra)              # load instruction LDQ PV,xxx($yy)
+       sll     $22,48,$22
+       sra     $22,48,$22              # isolate offset
+
+       addq    $22,$28,$22             # compute update address via method pointer
+       stq     $0,0($22)               # save new method address there
+
+    bis     $0,$0,pv                # load method address into pv
+
+       jmp     zero, (pv)              # and call method. The method returns
+                                       # directly to the caller (ra).
+
+       .end    asm_call_jit_compiler
+
+
+/****************** function asm_dumpregistersandcall **************************
+*                                                                              *
+*   This funtion saves all callee saved registers and calls the function       *
+*   which is passed as parameter.                                              *
+*                                                                              *
+*   This function is needed by the garbage collector, which needs to access    *
+*   all registers which are stored on the stack. Unused registers are          *
+*   cleared to avoid interferances with the GC.                                *
+*                                                                              *
+*   void asm_dumpregistersandcall (functionptr f);                             *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    asm_dumpregistersandcall
+asm_dumpregistersandcall:
+       lda     sp,-16*8(sp)            # allocate stack
+       stq     ra,0(sp)                # save return address
+
+       stq     $9,1*8(sp)              # save all callee saved registers
+       stq     $10,2*8(sp)             # intialize the remaining registers
+       stq     $11,3*8(sp)
+       stq     $12,4*8(sp)
+       stq     $13,5*8(sp)
+       stq     $14,6*8(sp)
+       stq     $15,7*8(sp)
+       stt     $f2,8*8(sp)
+       stt     $f3,9*8(sp)
+       stt     $f4,10*8(sp)
+       stt     $f5,11*8(sp)
+       stt     $f6,12*8(sp)
+       stt     $f7,13*8(sp)
+       stt     $f8,14*8(sp)
+       stt     $f9,15*8(sp)
+
+       bis     zero,zero,$0           # intialize the remaining registers
+       bis     zero,zero,$1
+       bis     zero,zero,$2
+       bis     zero,zero,$3
+       bis     zero,zero,$4
+       bis     zero,zero,$5
+       bis     zero,zero,$6
+       bis     zero,zero,$7
+       bis     zero,zero,$8
+       bis     zero,zero,$17
+       bis     zero,zero,$18
+       bis     zero,zero,$19
+       bis     zero,zero,$20
+       bis     zero,zero,$21
+       bis     zero,zero,$22
+       bis     zero,zero,$23
+       bis     zero,zero,$24
+       bis     zero,zero,$25
+       bis     zero,zero,$26
+       bis     zero,zero,$27
+       bis     zero,zero,$28
+       bis     zero,zero,$29
+       cpys    $f31,$f31,$f0
+       cpys    $f31,$f31,$f1
+       cpys    $f31,$f31,$f10
+       cpys    $f31,$f31,$f11
+       cpys    $f31,$f31,$f12
+       cpys    $f31,$f31,$f13
+       cpys    $f31,$f31,$f14
+       cpys    $f31,$f31,$f15
+       cpys    $f31,$f31,$f16
+       cpys    $f31,$f31,$f17
+       cpys    $f31,$f31,$f18
+       cpys    $f31,$f31,$f19
+       cpys    $f31,$f31,$f20
+       cpys    $f31,$f31,$f21
+       cpys    $f31,$f31,$f22
+       cpys    $f31,$f31,$f23
+       cpys    $f31,$f31,$f24
+       cpys    $f31,$f31,$f25
+       cpys    $f31,$f31,$f26
+       cpys    $f31,$f31,$f27
+       cpys    $f31,$f31,$f28
+       cpys    $f31,$f31,$f29
+       cpys    $f31,$f31,$f30
+
+       bis     $16,$16,pv              # load function pointer
+       jmp     ra,(pv)                 # and call function
+
+       ldq     ra,0(sp)                # load return address
+       lda     sp,16*8(sp)             # deallocate stack
+       jmp     zero,(ra)               # return
+
+       .end    asm_dumpregistersandcall
+
+
+/********************* function asm_handle_exception ***************************
+*                                                                              *
+*   This function handles an exception. It does not use the usual calling      *
+*   conventions. The exception pointer is passed in REG_ITMP1 and the          *
+*   pc from the exception raising position is passed in REG_ITMP2. It searches *
+*   the local exception table for a handler. If no one is found, it unwinds    *
+*   stacks and continues searching the callers.                                *
+*                                                                              *
+*   void asm_handle_exception (exceptionptr, exceptionpc);                     *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    asm_handle_nat_exception
+asm_handle_nat_exception:
+
+       ldl     t0,0(ra)                # load instruction LDA PV,xxx(RA)
+       sll     t0,48,t0
+       sra     t0,48,t0                # isolate offset
+       addq    t0,ra,pv                # compute update address
+       ldl     t0,4(ra)                # load instruction LDAH PV,xxx(PV)
+       srl     t0,16,t0                # isolate instruction code
+       lda     t0,-0x177b(t0)          # test for LDAH
+       bne     t0,asm_handle_exception       
+       ldl     t0,0(ra)                # load instruction LDA PV,xxx(RA)
+       sll     t0,16,t0                # compute high offset
+       addl    t0,0,t0                 # sign extend high offset
+       addq    t0,pv,pv                # compute update address
+
+       .aent    asm_handle_exception
+asm_handle_exception:
+
+       lda     sp,-18*8(sp)            # allocate stack
+       stq     t0,0*8(sp)              # save possible used registers
+       stq     t1,1*8(sp)              # also registers used by builtin_checkcast
+       stq     t2,2*8(sp)
+       stq     t3,3*8(sp)
+       stq     t4,4*8(sp)
+       stq     t5,5*8(sp)
+       stq     t6,6*8(sp)
+       stq     t7,7*8(sp)
+       stq     t8,8*8(sp)
+       stq     t9,9*8(sp)
+       stq     t10,10*8(sp)
+       stq     v0,11*8(sp)
+       stq     a0,12*8(sp)
+       stq     a1,13*8(sp)
+       stq     a2,14*8(sp)
+       stq     a3,15*8(sp)
+       stq     a4,16*8(sp)
+       stq     a5,17*8(sp)
+
+       lda     t3,1(zero)              # set no unwind flag
+ex_stack_loop:
+       lda     sp,-5*8(sp)             # allocate stack
+       stq     xptr,0*8(sp)            # save used register
+       stq     xpc,1*8(sp)
+       stq     pv,2*8(sp)
+       stq     ra,3*8(sp)
+       stq     t3,4*8(sp)
+
+       mov     xptr,a0
+       ldq     a1,MethodPointer(pv)
+       mov     xpc,a2
+       mov     t3,a3
+       br      ra,ex_trace             # set ra for gp loading
+ex_trace:
+       ldgp    gp,0(ra)                # load gp
+       jsr     ra,builtin_trace_exception # builtin_trace_exception(xptr,methodptr)
+       
+       ldq     xptr,0*8(sp)            # restore used register
+       ldq     xpc,1*8(sp)
+       ldq     pv,2*8(sp)
+       ldq     ra,3*8(sp)
+       ldq     t3,4*8(sp)
+       lda     sp,5*8(sp)              # deallocate stack
+       
+       ldl     t0,ExTableSize(pv)      # t0 = exception table size
+       beq     t0,empty_table          # if empty table skip
+       lda     t1,ExTableStart(pv)     # t1 = start of exception table
+
+ex_table_loop:
+       ldq     t2,ExStartPC(t1)        # t2 = exception start pc
+       cmple   t2,xpc,t2               # t2 = (startpc <= xpc)
+       beq     t2,ex_table_cont        # if (false) continue
+       ldq     t2,ExEndPC(t1)          # t2 = exception end pc
+       cmplt   xpc,t2,t2               # t2 = (xpc < endpc)
+       beq     t2,ex_table_cont        # if (false) continue
+       ldq     a1,ExCatchType(t1)      # arg1 = exception catch type
+       beq     a1,ex_handle_it         # NULL catches everything
+       mov     xptr,a0                 # arg0 = exception pointer
+
+       lda     sp,-7*8(sp)             # allocate stack
+       stq     t0,0*8(sp)              # save used register
+       stq     t1,1*8(sp)
+       stq     t3,2*8(sp)
+       stq     xptr,3*8(sp)
+       stq     xpc,4*8(sp)
+       stq     pv,5*8(sp)
+       stq     ra,6*8(sp)
+
+       br      ra,ex_gpload            # set ra for gp loading
+ex_gpload:
+       ldgp    gp,0(ra)                # load gp
+       jsr     ra,builtin_checkcast    # builtin_checkcast(xptr,catchtype)
+       
+       ldq     t0,0*8(sp)              # restore used register
+       ldq     t1,1*8(sp)
+       ldq     t3,2*8(sp)
+       ldq     xptr,3*8(sp)
+       ldq     xpc,4*8(sp)
+       ldq     pv,5*8(sp)
+       ldq     ra,6*8(sp)
+       lda     sp,7*8(sp)              # deallocate stack
+
+       beq     v0,ex_table_cont        # if (false) continue
+
+ex_handle_it:
+
+       ldq     xpc,ExHandlerPC(t1)     # xpc = exception handler pc
+
+       beq     t3,ex_jump              # if (!(no stack unwinding) skip
+
+       ldq     t0,0*8(sp)              # restore possible used registers
+       ldq     t1,1*8(sp)              # also registers used by builtin_checkcast
+       ldq     t2,2*8(sp)
+       ldq     t3,3*8(sp)
+       ldq     t4,4*8(sp)
+       ldq     t5,5*8(sp)
+       ldq     t6,6*8(sp)
+       ldq     t7,7*8(sp)
+       ldq     t8,8*8(sp)
+       ldq     t9,9*8(sp)
+       ldq     t10,10*8(sp)
+       ldq     v0,11*8(sp)
+       ldq     a0,12*8(sp)
+       ldq     a1,13*8(sp)
+       ldq     a2,14*8(sp)
+       ldq     a3,15*8(sp)
+       ldq     a4,16*8(sp)
+       ldq     a5,17*8(sp)
+       lda     sp,18*8(sp)             # deallocate stack
+
+ex_jump:
+       jmp     zero,(xpc)              # jump to the handler 
+
+ex_table_cont:
+       lda     t1,ExEntrySize(t1)      # next exception table entry
+       subl    t0,1,t0                 # decrement entry counter
+       bgt     t0,ex_table_loop        # if (t0 > 0) next entry
+
+empty_table:
+       beq     t3,ex_already_cleared   # if here the first time, then
+       lda     sp,18*8(sp)             # deallocate stack and
+       clr     t3                      # clear the no unwind flag
+ex_already_cleared:
+       ldl     t0,IsSync(pv)           # t0 = SyncOffset
+       beq     t0,no_monitor_exit      # if zero no monitorexit
+       addq    sp,t0,t0                # add Offset to stackptr
+       ldq     a0,-8(t0)               # load monitorexit pointer
+
+       lda     sp,-7*8(sp)             # allocate stack
+       stq     t0,0*8(sp)              # save used register
+       stq     t1,1*8(sp)
+       stq     t3,2*8(sp)
+       stq     xptr,3*8(sp)
+       stq     xpc,4*8(sp)
+       stq     pv,5*8(sp)
+       stq     ra,6*8(sp)
+
+       br      ra,ex_mon_load          # set ra for gp loading
+ex_mon_load:
+       ldgp    gp,0(ra)                # load gp
+       jsr     ra,builtin_monitorexit  # builtin_monitorexit(objectptr)
+       
+       ldq     t0,0*8(sp)              # restore used register
+       ldq     t1,1*8(sp)
+       ldq     t3,2*8(sp)
+       ldq     xptr,3*8(sp)
+       ldq     xpc,4*8(sp)
+       ldq     pv,5*8(sp)
+       ldq     ra,6*8(sp)
+       lda     sp,7*8(sp)              # deallocate stack
+
+no_monitor_exit:
+       ldl     t0,FrameSize(pv)        # t0 = frame size
+       addq    sp,t0,sp                # unwind stack
+       mov     sp,t0                   # t0 = pointer to save area
+       ldl     t1,IsLeaf(pv)           # t1 = is leaf procedure
+       bne     t1,ex_no_restore        # if (leaf) skip
+       ldq     ra,-8(t0)               # restore ra
+       lda     t0,-8(t0)               # t0--
+ex_no_restore:
+       mov     ra,xpc                  # the new xpc is ra
+       ldl     t1,IntSave(pv)          # t1 = saved int register count
+       br      t2,ex_int1              # t2 = current pc
+ex_int1:
+       lda     t2,44(t2)               # lda t2,ex_int2-ex_int1(t2) !!!!!!!!!!!!!!!
+       negl    t1,t1                   # negate register count
+       s4addq  t1,t2,t2                # t2 = ex_int_sav - 4 * register count
+       jmp     zero,(t2)               # jump to save position
+       ldq     s0,-56(t0)
+       ldq     s1,-48(t0)
+       ldq     s2,-40(t0)
+       ldq     s3,-32(t0)
+       ldq     s4,-24(t0)
+       ldq     s5,-16(t0)
+       ldq     s6,-8(t0)
+ex_int2:
+       s8addq  t1,t0,t0                # t0 = t0 - 8 * register count
+
+       ldl     t1,FltSave(pv)          # t1 = saved flt register count
+       br      t2,ex_flt1              # t2 = current pc
+ex_flt1:
+       lda     t2,48(t2)               # lda t2,ex_flt2-ex_flt1(t2) !!!!!!!!!!!!!!!
+       negl    t1,t1                   # negate register count
+       s4addq  t1,t2,t2                # t2 = ex_flt_sav - 4 * register count
+       jmp     zero,(t2)               # jump to save position
+       ldt     $f2,-64(t0)
+       ldt     $f3,-56(t0)
+       ldt     $f4,-48(t0)
+       ldt     $f5,-40(t0)
+       ldt     $f6,-32(t0)
+       ldt     $f7,-24(t0)
+       ldt     $f8,-16(t0)
+       ldt     $f9,-8(t0)
+ex_flt2:
+       ldl     t0,0(ra)                # load instruction LDA PV,xxx(RA)
+       sll     t0,48,t0
+       sra     t0,48,t0                # isolate offset
+       addq    t0,ra,pv                # compute update address
+       ldl     t0,4(ra)                # load instruction LDAH PV,xxx(PV)
+       srl     t0,16,t0                # isolate instruction code
+       lda     t0,-0x177b(t0)          # test for LDAH
+       bne     t0,ex_stack_loop       
+       ldl     t0,0(ra)                # load instruction LDA PV,xxx(RA)
+       sll     t0,16,t0                # compute high offset
+       addl    t0,0,t0                 # sign extend high offset
+       addq    t0,pv,pv                # compute update address
+       br      ex_stack_loop
+
+       .end    asm_handle_exception
+
+
+/********************* function asm_signal_exception ***************************
+*                                                                              *
+*   This function handles an exception which was catched by a signal.          *
+*                                                                              *
+*   void asm_signal_exception (exceptionptr, signalcontext);                   *
+*                                                                              *
+*******************************************************************************/
+
+#define     sigctxstack  0*8   /* sigstack state to restore       */
+#define     sigctxmask   1*8   /* signal mask to restore          */
+#define     sigctxpc     2*8   /* pc at time of signal            */
+#define     sigctxpsl    3*8   /* psl to retore                   */
+#define     sigctxr00    4*8   /* processor regs 0 to 31          */
+#define     sigctxr01    5*8
+#define     sigctxr02    6*8
+#define     sigctxr03    7*8
+#define     sigctxr04    8*8
+#define     sigctxr05    9*8
+#define     sigctxr06   10*8
+#define     sigctxr07   11*8
+#define     sigctxr08   12*8
+#define     sigctxr09   13*8
+#define     sigctxr10   14*8
+#define     sigctxr11   15*8
+#define     sigctxr12   16*8
+#define     sigctxr13   17*8
+#define     sigctxr14   18*8
+#define     sigctxr15   19*8
+#define     sigctxr16   20*8
+#define     sigctxr17   21*8
+#define     sigctxr18   22*8
+#define     sigctxr19   23*8
+#define     sigctxr20   24*8
+#define     sigctxr21   25*8
+#define     sigctxr22   26*8
+#define     sigctxr23   27*8
+#define     sigctxr24   28*8
+#define     sigctxr25   29*8
+#define     sigctxr26   30*8
+#define     sigctxr27   31*8
+#define     sigctxr28   32*8
+#define     sigctxr29   33*8
+#define     sigctxr30   34*8
+#define     sigctxr31   35*8
+
+#define     sigctxfpuse 36*8   /* fp has been used                */
+#define     sigctxf00   37*8   /* fp regs 0 to 31                 */
+#define     sigctxf01   38*8
+#define     sigctxf02   39*8
+#define     sigctxf03   40*8
+#define     sigctxf04   41*8
+#define     sigctxf05   42*8
+#define     sigctxf06   43*8
+#define     sigctxf07   44*8
+#define     sigctxf08   45*8
+#define     sigctxf09   46*8
+#define     sigctxf10   47*8
+#define     sigctxf11   48*8
+#define     sigctxf12   49*8
+#define     sigctxf13   50*8
+#define     sigctxf14   51*8
+#define     sigctxf15   52*8
+#define     sigctxf16   53*8
+#define     sigctxf17   54*8
+#define     sigctxf18   55*8
+#define     sigctxf19   56*8
+#define     sigctxf20   57*8
+#define     sigctxf21   58*8
+#define     sigctxf22   59*8
+#define     sigctxf23   60*8
+#define     sigctxf24   61*8
+#define     sigctxf25   62*8
+#define     sigctxf26   63*8
+#define     sigctxf27   64*8
+#define     sigctxf28   65*8
+#define     sigctxf29   66*8
+#define     sigctxf30   67*8
+#define     sigctxf31   68*8
+
+#define     sigctxhfpcr 69*8   /* floating point control register */
+#define     sigctxsfpcr 70*8   /* software fpcr                   */
+
+       .ent    asm_signal_exception
+asm_signal_exception:
+
+       mov     a0,xptr
+       mov     a1,sp
+       ldq     xpc,sigctxpc(sp)
+       ldq     v0,sigctxr00(sp)              # restore possible used registers
+       ldq     t0,sigctxr01(sp)
+       ldq     t1,sigctxr02(sp)
+       ldq     t2,sigctxr03(sp)
+       ldq     t3,sigctxr04(sp)
+       ldq     t4,sigctxr05(sp)
+       ldq     t5,sigctxr06(sp)
+       ldq     t6,sigctxr07(sp)
+       ldq     t7,sigctxr08(sp)
+       ldq     s0,sigctxr09(sp)
+       ldq     s1,sigctxr10(sp)
+       ldq     s2,sigctxr11(sp)
+       ldq     s3,sigctxr12(sp)
+       ldq     s4,sigctxr13(sp)
+       ldq     s5,sigctxr14(sp)
+       ldq     s6,sigctxr15(sp)
+       ldq     a0,sigctxr16(sp)
+       ldq     a1,sigctxr17(sp)
+       ldq     a2,sigctxr18(sp)
+       ldq     a3,sigctxr19(sp)
+       ldq     a4,sigctxr20(sp)
+       ldq     a5,sigctxr21(sp)
+       ldq     t8,sigctxr22(sp)
+       ldq     t9,sigctxr23(sp)
+       ldq     t10,sigctxr24(sp)
+       ldq     ra,sigctxr26(sp)
+       ldq     pv,sigctxr27(sp)
+       ldq     sp,sigctxr30(sp)
+       br      asm_handle_nat_exception
+       .end    asm_signal_exception
+
+
+/********************* function new_builtin_monitorenter ***********************
+*                                                                              *
+*   Does null check and calls monitorenter or throws an exception              *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_monitorenter
+new_builtin_monitorenter:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_monitorenter
+       beq     a0,nb_monitorenter          # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_monitorenter
+
+nb_monitorenter:
+       ldq     xptr,proto_java_lang_NullPointerException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_monitorenter
+
+
+/********************* function new_builtin_monitorexit ************************
+*                                                                              *
+*   Does null check and calls monitorexit or throws an exception               *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_monitorexit
+new_builtin_monitorexit:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_monitorexit
+       beq     a0,nb_monitorexit           # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_monitorexit
+
+nb_monitorexit:
+       ldq     xptr,proto_java_lang_NullPointerException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_monitorenter
+
+
+/************************ function new_builtin_idiv ****************************
+*                                                                              *
+*   Does null check and calls idiv or throws an exception                      *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_idiv
+new_builtin_idiv:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_idiv
+       beq     a1,nb_idiv                  # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_idiv
+
+nb_idiv:
+       ldq     xptr,proto_java_lang_ArithmeticException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_idiv
+
+
+/************************ function new_builtin_ldiv ****************************
+*                                                                              *
+*   Does null check and calls ldiv or throws an exception                      *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_ldiv
+new_builtin_ldiv:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_ldiv
+       beq     a1,nb_ldiv                  # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_ldiv
+
+nb_ldiv:
+       ldq     xptr,proto_java_lang_ArithmeticException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_ldiv
+
+
+/************************ function new_builtin_irem ****************************
+*                                                                              *
+*   Does null check and calls irem or throws an exception                      *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_irem
+new_builtin_irem:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_irem
+       beq     a1,nb_irem                  # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_irem
+
+nb_irem:
+       ldq     xptr,proto_java_lang_ArithmeticException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_irem
+
+
+/************************ function new_builtin_lrem ****************************
+*                                                                              *
+*   Does null check and calls lrem or throws an exception                      *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_lrem
+new_builtin_lrem:
+
+       ldgp    gp,0(pv)
+       lda     pv,builtin_lrem
+       beq     a1,nb_lrem                  # if (null) throw exception
+       jmp     zero,(pv)                   # else call builtin_lrem
+
+nb_lrem:
+       ldq     xptr,proto_java_lang_ArithmeticException
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_lrem
+
+
+/*********************** function new_builtin_checkcast ************************
+*                                                                              *
+*   Does the cast check and eventually throws an exception                     *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_checkcast
+new_builtin_checkcast:
+
+       ldgp    gp,0(pv)
+       lda     sp,-16(sp)                  # allocate stack space
+       stq     ra,0(sp)                    # save return address
+       stq     a0,8(sp)                    # save object pointer
+       jsr     ra,builtin_checkcast        # builtin_checkcast
+       ldgp    gp,0(ra)
+       beq     v0,nb_ccast_throw           # if (false) throw exception
+       ldq     ra,0(sp)                    # restore return address
+       ldq     v0,8(sp)                    # return object pointer
+       lda     sp,16(sp)                   # free stack space
+       jmp     zero,(ra)
+
+nb_ccast_throw:
+       ldq     xptr,proto_java_lang_ClassCastException
+       ldq     ra,0(sp)                    # restore return address
+       lda     sp,16(sp)                   # free stack space
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_checkcast
+
+
+/******************* function new_builtin_checkarraycast ***********************
+*                                                                              *
+*   Does the cast check and eventually throws an exception                     *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_checkarraycast
+new_builtin_checkarraycast:
+
+       ldgp    gp,0(pv)
+       lda     sp,-16(sp)                  # allocate stack space
+       stq     ra,0(sp)                    # save return address
+       stq     a0,8(sp)                    # save object pointer
+       jsr     ra,builtin_checkarraycast   # builtin_checkarraycast
+       ldgp    gp,0(ra)
+       beq     v0,nb_carray_throw          # if (false) throw exception
+       ldq     ra,0(sp)                    # restore return address
+       ldq     v0,8(sp)                    # return object pointer
+       lda     sp,16(sp)                   # free stack space
+       jmp     zero,(ra)
+
+nb_carray_throw:
+       ldq     xptr,proto_java_lang_ClassCastException
+       ldq     ra,0(sp)                    # restore return address
+       lda     sp,16(sp)                   # free stack space
+       lda     xpc,-4(ra)                  # faulting address is return adress - 4
+       br      asm_handle_nat_exception
+       .end    new_builtin_checkarraycast
+
+
+/******************* function new_builtin_aastore ******************************
+*                                                                              *
+*   Does the cast check and eventually throws an exception                     *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    new_builtin_aastore
+new_builtin_aastore:
+
+       ldgp    gp,0(pv)
+       beq     a0,nb_aastore_null          # if null pointer throw exception
+       ldl     t0,offarrsize(a0)           # load size
+       lda     sp,-24(sp)                  # allocate stack space
+       stq     ra,0(sp)                    # save return address
+       s8addq  a1,a0,t1                    # add index*8 to arrayref
+       cmpult  a1,t0,t0                    # do bound check
+       beq     t0,nb_aastore_bound         # if out of bounds throw exception
+       mov     a2,a1                       # object is second argument
+       stq     t1,8(sp)                    # save store position
+       stq     a1,16(sp)                   # save object
+       jsr     ra,builtin_canstore         # builtin_canstore(arrayref,object)
+       ldgp    gp,0(ra)
+       ldq     ra,0(sp)                    # restore return address
+       ldq     a0,8(sp)                    # restore store position
+       ldq     a1,16(sp)                   # restore object
+       lda     sp,24(sp)                   # free stack space
+       beq     v0,nb_aastore_throw         # if (false) throw exception
+       stq     a1,offobjarr(a0)            # store objectptr in array
+       jmp     zero,(ra)
+
+nb_aastore_null:
+       ldq     xptr,proto_java_lang_NullPointerException
+       mov     ra,xpc                      # faulting address is return adress 
+       br      asm_handle_nat_exception
+
+nb_aastore_bound:
+       ldq     xptr,proto_java_lang_ArrayIndexOutOfBoundsException
+       lda     sp,24(sp)                   # free stack space
+       mov     ra,xpc                      # faulting address is return adress 
+       br      asm_handle_nat_exception
+
+nb_aastore_throw:
+       ldq     xptr,proto_java_lang_ArrayStoreException
+       mov     ra,xpc                      # faulting address is return adress 
+       br      asm_handle_nat_exception
+
+       .end    new_builtin_aastore
+
+
+/********************** function initialize_thread_stack ***********************
+*                                                                              *
+*   initialized a thread stack                                                 *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    initialize_thread_stack
+initialize_thread_stack:
+
+       lda     a1,-128(a1)
+       stq     zero, 0(a1)
+       stq     zero, 8(a1)
+       stq     zero, 16(a1)
+       stq     zero, 24(a1)
+       stq     zero, 32(a1)
+       stq     zero, 40(a1)
+       stq     zero, 48(a1)
+       stt     fzero, 56(a1)
+       stt     fzero, 64(a1)
+       stt     fzero, 72(a1)
+       stt     fzero, 80(a1)
+       stt     fzero, 88(a1)
+       stt     fzero, 96(a1)
+       stt     fzero, 104(a1)
+       stt     fzero, 112(a1)
+       stq     a0, 120(a1)
+       mov     a1, v0
+       jmp     zero,(ra)
+       .end    initialize_thread_stack
+
+
+/******************* function perform_alpha_threadswitch ***********************
+*                                                                              *
+*   performs a threadswitch                                                    *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    perform_alpha_threadswitch
+perform_alpha_threadswitch:
+
+       subq    sp,128,sp                                 
+       stq     s0, 0(sp)
+       stq     s1, 8(sp)
+       stq     s2, 16(sp)
+       stq     s3, 24(sp)
+       stq     s4, 32(sp)
+       stq     s5, 40(sp)
+       stq     s6, 48(sp)
+       stt     sf0, 56(sp)
+       stt     sf1, 64(sp)
+       stt     sf2, 72(sp)
+       stt     sf3, 80(sp)
+       stt     sf4, 88(sp)
+       stt     sf5, 96(sp)
+       stt     sf6, 104(sp)
+       stt     sf7, 112(sp)
+       stq     ra, 120(sp)
+       stq     sp, 0(a0)
+       ldq     sp, 0(a1)
+       ldq     s0, 0(sp)
+       ldq     s1, 8(sp)
+       ldq     s2, 16(sp)
+       ldq     s3, 24(sp)
+       ldq     s4, 32(sp)
+       ldq     s5, 40(sp)
+       ldq     s6, 48(sp)
+       ldt     sf0, 56(sp)
+       ldt     sf1, 64(sp)
+       ldt     sf2, 72(sp)
+       ldt     sf3, 80(sp)
+       ldt     sf4, 88(sp)
+       ldt     sf5, 96(sp)
+       ldt     sf6, 104(sp)
+       ldt     sf7, 112(sp)
+       ldq     ra, 120(sp)
+       mov     ra, t12
+       addq    sp, 128, sp
+       jmp     zero,(ra)
+       .end    perform_alpha_threadswitch
+
+
+/*********************** function used_stack_top *******************************
+*                                                                              *
+*   returns $sp                                                                *
+*                                                                              *
+*******************************************************************************/
+
+       .ent    used_stack_top
+used_stack_top:
+
+       mov     sp, v0
+       jmp     zero,(ra)
+       .end    used_stack_top
diff --git a/alpha/calling.doc b/alpha/calling.doc
new file mode 100644 (file)
index 0000000..ab27b90
--- /dev/null
@@ -0,0 +1,182 @@
+/***************************** calling.doc *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Das ist eine kurze Dokumentation "uber die internen Aufrufskonventionen
+       der Java-Methoden in der DEC-ALHPA-Version.
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/02/05
+
+*******************************************************************************/
+FILE: calling.doc
+
+Das ist eine kurze Dokumentation "uber die internen Aufrufskonventionen
+der Java-Methoden in der DEC-ALHPA-Version.
+
+-------------------------------------------------------------------------------
+
+
+Die Aufrufskonventionen halten sich weitgehende an die Konventionen
+f"ur normale C-Funktionen, allerdings mit einigen zus"atzlichen
+Registerbelegungen:
+
+R28 ..... enth"alt bei einem Methodenaufruf auf jeden Fall den Zeiger 
+          auf die zugeh"orige 'methodinfo'-Struktur, die gegebenenfalls an
+          den JIT-Compiler weitergegeben werden muss. 
+
+          Wenn von Java-Methoden aus direkt C-Funktionen aufgerufen werden,
+          (f"ur die nat"urlich auch keine 'methodinfo'-Struktur existiert),
+          dann hat dieses Register keinen definierten Wert (Alle von der
+          JavaVM verwendeten Funktionen, z. B. 'builtin_new', etc. werden
+          so aufgerufen)
+          
+R1 ...... enth"alt nach Methodenbeendigung entweder NULL oder einen Zeiger
+          auf ein Objekt vom Typ java.lang.Throwable (oder einem davon
+          abgeleiteten Typ).
+          Wenn das der Fall ist, dann wurde in der Methode eine Exception
+          geworfen, die nicht abgefangen werden konnte, und jetzt beim
+          Aufrufer weiter bearbeitet werden muss.
+
+
+          
+Die restlichen Register folgen den normalen Konventionen, aber ich gebe
+hier noch einmal eine kurze "Ubersicht:
+
+INTEGER-REGISTER:
+
+R0 ........ R"uckgabewert von den Methoden f"ur die Typen:
+                    INT,LONG,ADDRESS
+                    
+R1 ........ Adresse der geworfenen Exception (oder NULL)
+
+R2-R8 ..... tempor"are Register (werden im Unterprogram zerst"ort)
+
+R9-R15 .... gesicherte Register (werden im Unterprogramm nicht ver"andert)
+
+R16-R21 ... Argumentregister 1 - 6 (hier werden die ersten sechs Methoden- 
+            Argumente eingetragen, sofern sie von den Typen INT,LONG,ADDRESS 
+            sind. Diese Argumentregister werden im Unterprogramm zerst"ort
+           
+R22-R24 ... tempor"are Register
+            (werden im Unterprogramm zerst"ort)                
+               
+R25 ....... tempor"ares Register f"ur kurzfristige Zwischenergebnisse
+            (wird im Unterprogramm zerst"ort)
+
+R26 (ra) .. R"ucksprungadresse (bleibt im Unterprogramm erhalten)
+
+R27 (pv) .. Prozedurzeiger. Dieses Register muss auf jeden Fall einen Zeiger
+            auf die aufgerufene Prozedur enthalten (damit die Zugriffe
+            auf das Datensegment funktionieren k"onnen).
+            (der Wert bleibt im Unterprogramm erhalten)
+
+R28 ....... Zeiger auf die 'methodinfo' - Struktur. Muss auf jeden Fall bei
+            allen Methodenaufrufen richtig gesetzt sein (wegen eines eventuellen
+            Compiler-Aufrufs)
+            (wird im Unterprogramm zerst"ort)
+            
+R29 ....... tempor"ares Register f"ur kurzfristige Zwischenergebnisse
+            (wird im Unterprogramm zerst"ort)
+
+R30 (sp) .. Zeiger auf die Untergrenze des Stack (der Stack w"achst von
+            oben nach unten)
+            
+R31 ....... enth"alt immer NULL
+
+
+FLIESSKOMMA-REGISTER:
+
+
+F0 ........ enth"alt die R"uckgabewert der Methoden vom Typ:
+                FLOAT, DOUBLE
+F1 ........ enth"alt den Imagin"aranteil von einem komplexen Funktionswert
+                (wird von mir nicht benutzt)
+                                
+F2-F9 ..... gesicherte Register (werden im Unterprogramm nicht ver"andert)
+
+F10-F15 ... tempor"are Register (werden im Unterprogramm zerst"ort)
+
+F16-F21 ... Argumentregister f"ur die ersten 6 Parameter, sofern diese
+            vom den Typen FLOAT oder DOUBLE sind
+            
+F22-F24 ... tempor"are Register (werden im Unterprogramm zerst"ort)
+
+F25-F31 ... tempor"are Register f"ur kurzfristige Zwischenergebnisse
+            (werden im Unterprogramm zerst"ort)
+
+F31 ....... enth"alt immer 0.0
+
+
+
+PARAMETER"UBERGABE AM STACK:
+
+Bei mehr als sechs Parametern reicht der Platz in den Registern nicht mehr
+aus, daf"ur werden alle Parameter ab dem Siebenten am Stack "ubergeben,
+und zwar nach folgendem Muster:
+
+
+                  | .....                                          |
+                                 --------------------------------------------------
+                  |  Parameter 9  ( 64 bit, egal bei welchem Typ)  |
+                  --------------------------------------------------
+                                 |  Parameter 8  ( 64 bit, egal bei welchem Typ   |
+                  --------------------------------------------------
+   R30 (sp) --->  |  Parameter 7  ( 64 bit, egal bei welchem Typ)  |
+                  --------------------------------------------------
+  
+Der Stackpointer zeigt dabei auf die Untergrenze des Parameterbereichs.
+
+
+
+
+
+VOLLST"ANDIGES LAYOUT EINES STACKFRAMES:
+
+Jede Methode muss (wenn es keine Leaf-Methode ist, auf jeden Fall) gewisse
+Registerinhalte am Stack sichern.
+Eventuell werden auch noch lokale Werte, die nicht mehr in Registern
+Platz finden, ebenfalls am Stack aufbewahrt, und die Parameter"ubergabe
+bei mehr als 6 Parametern ben"otigt ebenfalls Platz am Stack.
+
+Ein vollst"andiger Stackframe hat also dieses Aussehen (jeder Eintrag
+im Stackframe ist unabh"angig vom Typ auf jedem Fall 64 bit lang, die
+Gr"ossenangaben der Bereiche sind in solchen Einheiten von 64 Bit 
+angegeben):
+       
+                               ---------------------------------------------
+                               |  Parameter n (vom Aufrufer)               |
+                ---------------------------------------------                          
+                               |  Parameter n-1                            |
+                               ---------------------------------------------
+                | ...                                       |
+                ---------------------------------------------
+   SP vorher -> |  Parameter 7                              |
+                ============================================= --- 
+                |  gesichertes RA                           |  savedregs_num    
+                ---------------------------------------------
+                |  andere gesicherte Register               |
+                ============================================= ---
+                |  Platz f"ur lokale Werte, die nicht mehr  |  localvars_num
+                |  in Register passen                       |
+                ============================================= ---
+                |  ....                                     |  arguments_num
+                ---------------------------------------------
+                |  Parameter 8                              |
+                ---------------------------------------------
+   SP --->      |  Parameter 7 (f"ur aufgerufenen Methoden) |
+                ============================================= ---
+               
+                
+Damit die Anf"ange der einzelnen Bereiche (im Codegenerator) leichter 
+ausgedr"uckt werden k"onnen, sind ein paar Hilfsvariablen vorgesehen, die
+die Adressierung der einzelnen Bereiche vereinfachen:
+       localvars_base  = arguments_num
+       savedregs_base  = localvars_base + localvars_num
+       parentargs_base = savedregs_base + savedregs_num
+
diff --git a/alpha/cray.c b/alpha/cray.c
new file mode 100644 (file)
index 0000000..b585bc4
--- /dev/null
@@ -0,0 +1,358 @@
+/****************************** asmpart.c **************************************
+*                                                                              *
+*   is an assembly language file, but called .c to fake the preprocessor.      *
+*   It contains the Java-C interace functions for Alpha processors.           *
+*                                                                              *
+*   Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst              *
+*                                                                              *
+*   See file COPYRIGHT for information on usage and disclaimer of warranties   *
+*                                                                              *
+*   Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at            *
+*            Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at            *
+*                                                                              *
+*   Last Change: 1997/04/26                                                    *
+*                                                                              *
+*******************************************************************************/
+
+#define v0      r0
+
+#define t0      r1
+#define t1      r2
+#define t2      r3
+#define t3      r4
+#define t4      r5
+#define t5      r6
+#define t6      r7
+#define t7      r8
+
+#define        s0      r9
+#define        s1      r10
+#define        s2      r11
+#define        s3      r12
+#define        s4      r13
+#define        s5      r14
+#define        s6      r15
+
+#define a0      r16
+#define a1      r17
+#define a2      r18
+#define a3      r19
+#define a4      r20
+#define a5      r21
+
+#define t8      r22
+#define t9      r23
+#define t10     r24
+#define t11     r25
+#define ra      r26
+#define t12     r27
+
+#define pv      t12
+#define AT      .
+#define gp      r29
+#define sp      r30
+#define zero    r31
+
+#define PAL_imb 134
+
+
+/*     .set    noat
+       .set    noreorder
+*/
+
+       
+/********************* exported functions and variables ***********************/
+
+/*     .globl has_no_x_instr_set
+       .globl synchronize_caches
+       .globl asm_calljavamethod
+       .globl asm_call_jit_compiler
+       .globl asm_dumpregistersandcall
+*/
+
+/*************************** imported functions *******************************/
+
+/*     .globl  compiler_compile
+*/
+
+/*********************** function has_no_x_instr_set ***************************
+*                                                                              *
+*   determines if the byte support instruction set (21164a and higher)         *
+*   is available.                                                              *
+*                                                                              *
+*******************************************************************************/
+       zero <- t0
+       
+       .ident    has_no_x_instr_set
+       .psect code_sec, code
+has_no_x_instr_set::
+
+/*     .long   0x47e03c20                  ; amask   1,r0
+*/
+
+       zap   r0,1,r0
+
+       jmp     zero,(ra)                   ; return
+
+       .end    has_no_x_instr_set
+
+
+/********************* function synchronize_caches ****************************/
+
+       .ident    synchronize_caches
+       .psect code_sec, code
+synchronize_caches::
+
+       call_pal PAL_imb                    ; synchronise instruction cache
+       jmp     zero,(ra)                   ; return
+
+       .end    synchronize_caches
+
+
+
+/********************* function asm_calljavamethod *****************************
+*                                                                              *
+*   This function calls a Java-method (which possibly needs compilation)       *
+*   with up to 4 parameters.                                                   *
+*                                                                              *
+*   This functions calls the JIT-compiler which eventually translates the      *
+*   method into machine code.                                                  *
+*                                                                              *
+*   An possibly throwed exception will be returned to the caller as function   *
+*   return value, so the java method cannot return a fucntion value (this      *
+*   function usually calls 'main' and '<clinit>' which do not return a         *
+*   function value).                                                           *
+*                                                                              *
+*   C-prototype:                                                               *
+*    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
+*         void *arg1, void *arg2, void *arg3, void *arg4);                     *
+*                                                                              *
+*******************************************************************************/
+
+       .ident    asm_calljavamethod
+       .psect codesect3, code
+       .external asm_call_jit_compiler
+       
+asm_calljavamethod::
+
+;      ldgp    gp,0(pv)
+;      .prologue  1
+       lda     sp,-24(sp)                  ; allocate stack space
+       stq     ra,0(sp)                    ; save return address
+
+       stq     r16,16(sp)                  ; save method pointer for compiler
+       lda     r0,16(sp)                   ; pass pointer to method pointer via r0
+
+       bis     r17,r17,r16                 ; pass the remaining parameters
+       bis     r18,r18,r17
+       bis     r19,r19,r18
+       bis     r20,r20,r19
+
+       la     r28,asm_call_jit_compiler   ; fake virtual function call
+       ; Changed!! from lda
+       
+       stq     r28,8(sp)                   ; store function address
+       bis     sp,sp,r28                   ; set method pointer
+
+       ldq     pv,8(r28)                   ; method call as in Java
+       jmp     ra,(pv)                     ; call JIT compiler
+
+       ldq     ra,0(sp)                    ; restore return address
+       lda     sp,24(sp)                   ; free stack space
+
+       bis     r1,r1,r0                    ; pass exception to caller (C)
+       jmp     zero,(ra)
+
+       .end    asm_calljavamethod
+
+
+/****************** function asm_call_jit_compiler *****************************
+*                                                                              *
+*   invokes the compiler for untranslated JavaVM methods.                      *
+*                                                                              *
+*   Register R0 contains a pointer to the method info structure (prepared      *
+*   by createcompilerstub). Using the return address in R26 and the            *
+*   offset in the LDA instruction or using the value in methodptr R28 the      *
+*   patching address for storing the method address can be computed:           *
+*                                                                              *
+*   method address was either loaded using                                     *
+*   M_LDQ (REG_PV, REG_PV, a)        ; invokestatic/special    (r27)           *
+*   M_LDA (REG_PV, REG_RA, low)                                                *
+*   M_LDAH(REG_PV, REG_RA, high)     ; optional                                *
+*   or                                                                         *
+*   M_LDQ (REG_PV, REG_METHODPTR, m) ; invokevirtual/interace (r28)           *
+*   in the static case the method pointer can be computed using the            *
+*   return address and the lda function following the jmp instruction          *
+*                                                                              *
+*******************************************************************************/
+
+
+       .ident    asm_call_jit_compiler
+       .psect code_sec1, code
+       .external compiler_compile
+
+asm_call_jit_compiler::
+
+;      ldgp    gp,0(pv)
+;      .prologue  1
+       ldl     r22,-8(ra)              ; load instruction LDQ PV,xxx(ryy)
+       srl     r22,16,r22              ; shift right register number ryy
+       and     r22,31,r22              ; isolate register number
+       subl    r22,28,r22              ; test for REG_METHODPTR
+       beq     r22,noregchange       
+       ldl     r22,0(ra)               ; load instruction LDA PV,xxx(RA)
+       sll     r22,48,r22
+       sra     r22,48,r22              ; isolate offset
+       addq    r22,ra,r28              ; compute update address
+       ldl     r22,4(ra)               ; load instruction LDAH PV,xxx(PV)
+       srl     r22,16,r22              ; isolate instruction code
+       lda     r22,-0x177b(r22)        ; test for LDAH
+       bne     r22,noregchange       
+       ldl     r22,0(ra)               ; load instruction LDA PV,xxx(RA)
+       sll     r22,16,r22              ; compute high offset
+       addl    r22,0,r22               ; sign extend high offset
+       addq    r22,r28,r28             ; compute update address
+noregchange:
+       lda     sp,-14*8(sp)            ; reserve stack space
+       stq     r16,0*8(sp)             ; save all argument registers
+       stq     r17,1*8(sp)             ; they could be used by method
+       stq     r18,2*8(sp)
+       stq     r19,3*8(sp)
+       stq     r20,4*8(sp)
+       stq     r21,5*8(sp)
+       stt     f16,6*8(sp)
+       stt     f17,7*8(sp)
+       stt     f18,8*8(sp)
+       stt     f19,9*8(sp)
+       stt     f20,10*8(sp)
+       stt     f21,11*8(sp)
+       stq     r28,12*8(sp)            ; save method pointer
+       stq     ra,13*8(sp)             ; save return address
+
+       ldq     r16,0(r0)               ; pass 'methodinfo' pointer to
+       bsr     ra,compiler_compile     ; compiler
+;      ldgp    gp,0(ra)
+
+       call_pal PAL_imb                ; synchronise instruction cache
+
+       ldq     r16,0*8(sp)             ; load argument registers
+       ldq     r17,1*8(sp)
+       ldq     r18,2*8(sp)
+       ldq     r19,3*8(sp)
+       ldq     r20,4*8(sp)
+       ldq     r21,5*8(sp)
+       ldt     f16,6*8(sp)
+       ldt     f17,7*8(sp)
+       ldt     f18,8*8(sp)
+       ldt     f19,9*8(sp)
+       ldt     f20,10*8(sp)
+       ldt     f21,11*8(sp)
+       ldq     r28,12*8(sp)            ; load method pointer
+       ldq     ra,13*8(sp)             ; load return address
+       lda     sp,14*8(sp)             ; deallocate stack area
+
+       ldl     r22,-8(ra)              ; load instruction LDQ PV,xxx(ryy)
+       sll     r22,48,r22
+       sra     r22,48,r22              ; isolate offset
+
+       addq    r22,r28,r22             ; compute update address via method pointer
+       stq     r0,0(r22)               ; save new method address there
+
+    bis     r0,r0,pv                ; load method address into pv
+
+       jmp     zero, (pv)              ; and call method. The method returns
+                                       ; directly to the caller (ra).
+                                                                
+       .end    asm_call_jit_compiler
+
+
+/****************** function asm_dumpregistersandcall **************************
+*                                                                              *
+*   This funtion saves all callee saved registers and calls the function       *
+*   which is passed as parameter.                                              *
+*                                                                              *
+*   This function is needed by the garbage collector, which needs to access    *
+*   all registers which are stored on the stack. Unused registers are          *
+*   cleared to avoid intererances with the GC.                                *
+*                                                                              *
+*   void asm_dumpregistersandcall (functionptr f);                             *
+*                                                                              *
+*******************************************************************************/
+
+       .ident    asm_dumpregistersandcall
+       .psect code_sec2, code
+asm_dumpregistersandcall::
+       lda     sp,-16*8(sp)            ; allocate stack
+       stq     ra,0(sp)                ; save return address
+
+       stq     r9,1*8(sp)              ; save all callee saved registers
+       stq     r10,2*8(sp)             ; intialize the remaining registers
+       stq     r11,3*8(sp)
+       stq     r12,4*8(sp)
+       stq     r13,5*8(sp)
+       stq     r14,6*8(sp)
+       stq     r15,7*8(sp)
+       stt     f2,8*8(sp)
+       stt     f3,9*8(sp)
+       stt     f4,10*8(sp)
+       stt     f5,11*8(sp)
+       stt     f6,12*8(sp)
+       stt     f7,13*8(sp)
+       stt     f8,14*8(sp)
+       stt     f9,15*8(sp)
+
+       bis     zero,zero,r0           ; intialize the remaining registers
+       bis     zero,zero,r1
+       bis     zero,zero,r2
+       bis     zero,zero,r3
+       bis     zero,zero,r4
+       bis     zero,zero,r5
+       bis     zero,zero,r6
+       bis     zero,zero,r7
+       bis     zero,zero,r8
+       bis     zero,zero,r17
+       bis     zero,zero,r18
+       bis     zero,zero,r19
+       bis     zero,zero,r20
+       bis     zero,zero,r21
+       bis     zero,zero,r22
+       bis     zero,zero,r23
+       bis     zero,zero,r24
+       bis     zero,zero,r25
+       bis     zero,zero,r26
+       bis     zero,zero,r27
+       bis     zero,zero,r28
+       bis     zero,zero,r29
+       cpys    f31,f31,f0
+       cpys    f31,f31,f1
+       cpys    f31,f31,f10
+       cpys    f31,f31,f11
+       cpys    f31,f31,f12
+       cpys    f31,f31,f13
+       cpys    f31,f31,f14
+       cpys    f31,f31,f15
+       cpys    f31,f31,f16
+       cpys    f31,f31,f17
+       cpys    f31,f31,f18
+       cpys    f31,f31,f19
+       cpys    f31,f31,f20
+       cpys    f31,f31,f21
+       cpys    f31,f31,f22
+       cpys    f31,f31,f23
+       cpys    f31,f31,f24
+       cpys    f31,f31,f25
+       cpys    f31,f31,f26
+       cpys    f31,f31,f27
+       cpys    f31,f31,f28
+       cpys    f31,f31,f29
+       cpys    f31,f31,f30
+
+       bis     r16,r16,pv              ; load function pointer
+       jmp     ra,(pv)                 ; and call function
+
+       ldq     ra,0(sp)                ; load return address
+       lda     sp,16*8(sp)             ; deallocate stack
+       jmp     zero,(ra)               ; return
+
+       .end    
+
diff --git a/alpha/defines.h b/alpha/defines.h
new file mode 100644 (file)
index 0000000..e64e10b
--- /dev/null
@@ -0,0 +1,19 @@
+/*************************** alpha/defines.h ***********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       system-dependent definitions
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/09/11
+
+*******************************************************************************/
+
+#define USE_INTERNAL_THREADS
+
+#define HAVE_FCNTL
+#define HAVE_IOCTL
diff --git a/alpha/disass.c b/alpha/disass.c
new file mode 100644 (file)
index 0000000..f432506
--- /dev/null
@@ -0,0 +1,301 @@
+/********************************* disass.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       A very primitive disassembler for Alpha machine code for easy debugging.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/22
+
+*******************************************************************************/
+
+
+#define ITYPE_UNDEF 0
+#define ITYPE_JMP   1
+#define ITYPE_MEM   2
+#define ITYPE_BRA   3
+#define ITYPE_OP    4
+#define ITYPE_FOP   5
+
+static struct { int op; char *name; int itype; } ops[] = {
+       { 0x00, "",      ITYPE_UNDEF},
+       { 0x01, "",      ITYPE_UNDEF},
+       { 0x02, "",      ITYPE_UNDEF},
+       { 0x03, "",      ITYPE_UNDEF},
+       { 0x04, "",      ITYPE_UNDEF},
+       { 0x05, "",      ITYPE_UNDEF},
+       { 0x06, "",      ITYPE_UNDEF},
+       { 0x07, "",      ITYPE_UNDEF},
+       { 0x08, "LDA    ", ITYPE_MEM},
+       { 0x09, "LDAH   ", ITYPE_MEM},
+       { 0x0a, "LDB    ", ITYPE_MEM},
+       { 0x0b, "LDQ_U  ", ITYPE_MEM},
+       { 0x0c, "LDW    ", ITYPE_MEM},
+       { 0x0d, "STW    ", ITYPE_MEM},
+       { 0x0e, "STB    ", ITYPE_MEM},
+       { 0x0f, "STQ_U  ", ITYPE_MEM},
+       { 0x10, "OP     ",  ITYPE_OP},
+       { 0x11, "OP     ",  ITYPE_OP},
+       { 0x12, "OP     ",  ITYPE_OP},
+       { 0x13, "OP     ",  ITYPE_OP},
+       { 0x14, "",      ITYPE_UNDEF},
+       { 0x15, "",      ITYPE_UNDEF},
+       { 0x16, "FOP    ", ITYPE_FOP},
+       { 0x17, "FOP    ", ITYPE_FOP},
+       { 0x18, "MEMFMT ", ITYPE_MEM},
+       { 0x19, "",      ITYPE_UNDEF},
+       { 0x1a, "JMP    ", ITYPE_JMP},
+       { 0x1b, "",      ITYPE_UNDEF},
+       { 0x1c, "OP     ",  ITYPE_OP},
+       { 0x1d, "",      ITYPE_UNDEF},
+       { 0x1e, "",      ITYPE_UNDEF},
+       { 0x1f, "",      ITYPE_UNDEF},
+       { 0x20, "LDF    ", ITYPE_MEM},
+       { 0x21, "LDG    ", ITYPE_MEM},
+       { 0x22, "LDS    ", ITYPE_MEM},
+       { 0x23, "LDT    ", ITYPE_MEM},
+       { 0x24, "STF    ", ITYPE_MEM},
+       { 0x25, "STG    ", ITYPE_MEM},
+       { 0x26, "STS    ", ITYPE_MEM},
+       { 0x27, "STT    ", ITYPE_MEM},
+       { 0x28, "LDL    ", ITYPE_MEM},
+       { 0x29, "LDQ    ", ITYPE_MEM},
+       { 0x2a, "LDL_L  ", ITYPE_MEM},
+       { 0x2b, "LDQ_L  ", ITYPE_MEM},
+       { 0x2c, "STL    ", ITYPE_MEM},
+       { 0x2d, "STQ    ", ITYPE_MEM},
+       { 0x2e, "STL_C  ", ITYPE_MEM},
+       { 0x2f, "STQ_C  ", ITYPE_MEM},
+       { 0x30, "BR     ", ITYPE_BRA},
+       { 0x31, "FBEQ   ", ITYPE_BRA},
+       { 0x32, "FBLT   ", ITYPE_BRA},
+       { 0x33, "FBLE   ", ITYPE_BRA},
+       { 0x34, "BSR    ", ITYPE_BRA},
+       { 0x35, "FBNE   ", ITYPE_BRA},
+       { 0x36, "FBGE   ", ITYPE_BRA},
+       { 0x37, "FBGT   ", ITYPE_BRA},
+       { 0x38, "BLBC   ", ITYPE_BRA},
+       { 0x39, "BEQ    ", ITYPE_BRA},
+       { 0x3a, "BLT    ", ITYPE_BRA},
+       { 0x3b, "BLE    ", ITYPE_BRA},
+       { 0x3c, "BLBS   ", ITYPE_BRA},
+       { 0x3d, "BNE    ", ITYPE_BRA},
+       { 0x3e, "BGE    ", ITYPE_BRA},
+       { 0x3f, "BGT    ", ITYPE_BRA}
+};
+               
+static struct { u2 op,fun; char *name; }  op3s[] = {
+       { 0x10, 0x00,  "ADDL   " },
+       { 0x10, 0x40,  "ADDL/V " },
+       { 0x10, 0x20,  "ADDQ   " },
+       { 0x10, 0x60,  "ADDQ/V " },
+       { 0x10, 0x09,  "SUBL   " },
+       { 0x10, 0x49,  "SUBL/V " },
+       { 0x10, 0x29,  "SUBQ   " },
+       { 0x10, 0x69,  "SUBQ/V " },
+       { 0x10, 0x2D,  "CMPEQ  " },
+       { 0x10, 0x4D,  "CMPLT  " },
+       { 0x10, 0x6D,  "CMPLE  " },
+       { 0x10, 0x1D,  "CMPULT " },
+       { 0x10, 0x3D,  "CMPULE " },
+       { 0x10, 0x0F,  "CMPBGE " },
+       { 0x10, 0x02,  "S4ADDL " },
+       { 0x10, 0x0b,  "S4SUBL " },
+       { 0x10, 0x22,  "S4ADDQ " },
+       { 0x10, 0x2b,  "S4SUBQ " },
+       { 0x10, 0x12,  "S8ADDL " },
+       { 0x10, 0x1b,  "S8SUBL " },
+       { 0x10, 0x32,  "S8ADDQ " },
+       { 0x10, 0x3b,  "S8SUBQ " },
+       { 0x11, 0x00,  "AND    " },
+       { 0x11, 0x20,  "OR     " },
+       { 0x11, 0x40,  "XOR    " },
+       { 0x11, 0x08,  "ANDNOT " },
+       { 0x11, 0x28,  "ORNOT  " },
+       { 0x11, 0x48,  "XORNOT " },
+       { 0x11, 0x24,  "CMOVEQ " },
+       { 0x11, 0x44,  "CMOVLT " },
+       { 0x11, 0x64,  "CMOVLE " },
+       { 0x11, 0x26,  "CMOVNE " },
+       { 0x11, 0x46,  "CMOVGE " },
+       { 0x11, 0x66,  "CMOVGT " },
+       { 0x11, 0x14,  "CMOVLBS" },
+       { 0x11, 0x16,  "CMOVLBC" },
+       { 0x12, 0x39,  "SLL    " },
+       { 0x12, 0x3C,  "SRA    " },
+       { 0x12, 0x34,  "SRL    " },
+       { 0x12, 0x30,  "ZAP    " },
+       { 0x12, 0x31,  "ZAPNOT " },
+       { 0x12, 0x06,  "EXTBL  " },
+       { 0x12, 0x16,  "EXTWL  " },
+       { 0x12, 0x26,  "EXTLL  " },
+       { 0x12, 0x36,  "EXTQL  " },
+       { 0x12, 0x5a,  "EXTWH  " },
+       { 0x12, 0x6a,  "EXTLH  " },
+       { 0x12, 0x7a,  "EXTQH  " },
+       { 0x12, 0x0b,  "INSBL  " },
+       { 0x12, 0x1b,  "INSWL  " },
+       { 0x12, 0x2b,  "INSLL  " },
+       { 0x12, 0x3b,  "INSQL  " },
+       { 0x12, 0x57,  "INSWH  " },
+       { 0x12, 0x67,  "INSLH  " },
+       { 0x12, 0x77,  "INSQH  " },
+       { 0x12, 0x02,  "MSKBL  " },
+       { 0x12, 0x12,  "MSKWL  " },
+       { 0x12, 0x22,  "MSKLL  " },
+       { 0x12, 0x32,  "MSKQL  " },
+       { 0x12, 0x52,  "MSKWH  " },
+       { 0x12, 0x62,  "MSKLH  " },
+       { 0x12, 0x72,  "MSKQH  " },
+       { 0x13, 0x00,  "MULL   " },
+       { 0x13, 0x60,  "MULQ/V " },
+       { 0x13, 0x40,  "MULL/V " },
+       { 0x13, 0x30,  "UMULH  " },
+       { 0x16, 0x080, "FADD   " },
+       { 0x16, 0x0a0, "DADD   " },
+       { 0x16, 0x081, "FSUB   " },
+       { 0x16, 0x0a1, "DSUB   " },
+       { 0x16, 0x082, "FMUL   " },
+       { 0x16, 0x0a2, "DMUL   " },
+       { 0x16, 0x083, "FDIV   " },
+       { 0x16, 0x0a3, "DDIV   " },
+       { 0x16, 0x580, "FADDS  " },
+       { 0x16, 0x5a0, "DADDS  " },
+       { 0x16, 0x581, "FSUBS  " },
+       { 0x16, 0x5a1, "DSUBS  " },
+       { 0x16, 0x582, "FMULS  " },
+       { 0x16, 0x5a2, "DMULS  " },
+       { 0x16, 0x583, "FDIVS  " },
+       { 0x16, 0x5a3, "DDIVS  " },
+       { 0x16, 0x0ac, "CVTDF  " },
+       { 0x16, 0x0bc, "CVTLF  " },
+       { 0x16, 0x0be, "CVTLD  " },
+       { 0x16, 0x0af, "CVTDL  " },
+       { 0x16, 0x02f, "CVTDLC " },
+       { 0x16, 0x5ac, "CVTDFS " },
+       { 0x16, 0x5af, "CVTDLS " },
+       { 0x16, 0x52f, "CVTDLCS" },
+       { 0x16, 0x0a4, "FCMPUN " },
+       { 0x16, 0x0a5, "FCMPEQ " },
+       { 0x16, 0x0a6, "FCMPLT " },
+       { 0x16, 0x0a7, "FCMPLE " },
+       { 0x16, 0x5a4, "FCMPUNS" },
+       { 0x16, 0x5a5, "FCMPEQS" },
+       { 0x16, 0x5a6, "FCMPLTS" },
+       { 0x16, 0x5a7, "FCMPLES" },
+       { 0x17, 0x020, "FMOV   " },
+       { 0x17, 0x021, "FMOVN  " },
+       { 0x1c, 0x0,   "BSEXT  " },
+       { 0x1c, 0x1,   "WSEXT  " },
+       
+       { 0x00, 0x00,  NULL }
+};
+
+
+static void disasscmd (int c, int pos)
+{
+       int op, opfun, fopfun, i;
+       int ra, rb, rc, lit, disp;
+
+       op     = (c>>26) & 0x3f;
+       opfun  = (c>>5)  & 0x7f;
+       fopfun = (c>>5)  & 0x7ff;
+       ra     = (c>>21) & 0x1f;
+       rb     = (c>>16) & 0x1f;
+       rc     = (c>>0)  & 0x1f;
+       lit    = (c>>13) & 0xff;
+       disp   = (c<<16) >> 16;
+
+       printf ("%6x: %8x  ", pos, c);
+       
+       switch ( ops[op].itype ) {
+       case ITYPE_JMP:
+               switch ((c>>14) & 3) {
+                       case 0:
+                               printf ("JMP     "); 
+                               break;
+                       case 1:
+                               printf ("JSR     "); 
+                               break;
+                       case 2:
+                               printf ("RET     "); 
+                               break;
+                       case 3:
+                               printf ("JSR_CO  "); 
+                               break;
+                       }
+               printf ("$%d,$%d\n", ra, rb); 
+               break;
+
+       case ITYPE_MEM:
+               if (op == 0x18 && ra == 0 && ra == 0 && disp == 0)
+                       printf ("TRAPB\n"); 
+               else
+                       printf ("%s $%d,$%d,%d\n", ops[op].name, ra, rb, disp); 
+               break;
+
+       case ITYPE_BRA:
+               printf ("%s $%d,%x\n", ops[op].name, ra, pos + 4 + ((c << 11) >> 9));
+               break;
+               
+       case ITYPE_FOP:
+               if (op == 0x17 && fopfun == 0x020 && ra == rb) {
+                       if (ra == 31 && rc == 31)
+                               printf ("FNOP\n");
+                       else
+                               printf ("FMOV    $f%d,$f%d\n", ra, rc);
+                       return;
+                       }
+               for (i = 0; op3s[i].name; i++)
+                       if (op3s[i].op == op && op3s[i].fun == fopfun) {
+                               printf ("%s $f%d,$f%d,$f%d\n", op3s[i].name, ra, rb,  rc);
+                               return;
+                               }
+               printf ("%s%x $f%d,$f%d,$f%d\n", ops[op].name, fopfun, ra, rb, rc);
+               break; 
+
+       case ITYPE_OP:
+               if (op == 0x11 && opfun == 0x20 && ra == rb && ~(c&0x1000)) {
+                       if (ra == 31 && rc == 31)
+                               printf ("NOP\n");
+                       else
+                               printf ("MOV     $%d,$%d\n", ra, rc);
+                       return;
+                       }
+               for (i = 0; op3s[i].name; i++) {
+                       if (op3s[i].op == op && op3s[i].fun == opfun) {
+                               if (c&0x1000)
+                                       printf ("%s $%d,#%d,$%d\n", op3s[i].name, ra, lit, rc);
+                               else
+                                       printf ("%s $%d,$%d,$%d\n", op3s[i].name, ra, rb,  rc);
+                               return;
+                               }
+                       }
+               /* fall through */
+       default:
+               if (c&0x1000)
+                       printf ("UNDEF  %x(%x) $%d,#%d,$%d\n", op, opfun, ra, lit, rc);
+               else
+                       printf ("UNDEF  %x(%x) $%d,$%d,$%d\n", op, opfun, ra, rb,  rc);         
+       }
+}
+
+
+/*********************** funktion disassemble **********************************
+
+       outputs a disassembler listing of some machine code on 'stdout'
+
+*******************************************************************************/
+
+static void disassemble (int *code, int len)
+{
+       int p;
+
+       printf ("  --- disassembler listing ---\n");    
+       for (p = 0; p < len; p += 4, code++)
+               disasscmd (*code, p); 
+}
diff --git a/alpha/gen.c b/alpha/gen.c
new file mode 100644 (file)
index 0000000..467b6be
--- /dev/null
@@ -0,0 +1,1847 @@
+/***************************** alpha/gen.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (PCMDs).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/22
+
+*******************************************************************************/
+
+
+
+/*******************************************************************************
+
+Datatypes and Register Allocations:
+----------------------------------- 
+
+On 64-bit-machines (like the Alpha) all operands are stored in the
+registers in a 64-bit form, even when the correspondig JavaVM 
+operands only need 32 bits.
+This is done by a canonical representation:
+
+32-bit integers are allways stored as sign-extended 64-bit values
+(this approach is directly supported by the Alpha architecture and
+is very easy to implement).
+
+32-bit-floats are stored in a 64-bit doubleprecision register by
+simply expanding the exponent and mantissa with zeroes.
+(also supported by the architecture)
+
+
+Stackframes:
+
+The calling conventions and the layout of the stack is 
+explained in detail in the documention file: calling.doc
+
+*******************************************************************************/
+
+
+/************************ Preallocated registers ******************************/
+
+/* integer registers */
+  
+#define REG_RESULT      0    /* to deliver method results                     */ 
+#define REG_EXCEPTION          1    /* to throw an exception across method bounds    */
+
+#define REG_RA                 26   /* return address                                */
+#define REG_PV                 27   /* procedure vector, must be provided by caller  */
+#define REG_METHODPTR  28   /* pointer to the place from where the procedure */
+                             /* vector has been fetched                       */
+#define REG_ITMP1              25   /* temporary register                            */
+#define REG_ITMP2              28   /* temporary register                            */
+#define REG_ITMP3              29   /* temporary register                            */
+
+#define REG_SP                 30   /* stack pointer                                 */
+#define REG_ZERO               31   /* allways zero                                  */
+
+/* floating point registers */
+
+#define REG_FRESULT     0    /* to deliver floating point method results      */ 
+#define REG_FTMP1       28   /* temporary floating point register             */
+#define REG_FTMP2       29   /* temporary floating point register             */
+#define REG_FTMP3       30   /* temporary floating point register             */
+
+
+/******************** register descripton - array *****************************/
+
+/* #define REG_RES   0         reserved register for OS or code generator */
+/* #define REG_RET   1         return value register */
+/* #define REG_EXC   2         exception value register */
+/* #define REG_SAV   3         (callee) saved register */
+/* #define REG_TMP   4         scratch temporary register (caller saved) */
+/* #define REG_ARG   5         argument register (caller saved) */
+
+/* #define REG_END   -1        last entry in tables */
+int regdescint[] = {
+       REG_RET, REG_EXC, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, 
+       REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, 
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+       REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
+       REG_END };
+
+#define INT_SAV_FST      9   /* first int callee saved register               */
+#define INT_SAV_CNT      7   /* number of int callee saved registers          */
+#define INT_ARG_FST     16   /* first int callee saved register               */
+#define INT_ARG_CNT      6   /* number of int callee saved registers          */
+
+/* for use of reserved registers, see comment above */
+       
+int regdescfloat[] = {
+       REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+       REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, 
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+       REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
+       REG_END };
+
+#define FLT_SAV_FST      2   /* first int callee saved register               */
+#define FLT_SAV_CNT      8   /* number of int callee saved registers          */
+#define FLT_ARG_FST     16   /* first int callee saved register               */
+#define FLT_ARG_CNT      6   /* number of int callee saved registers          */
+
+/* for use of reserved registers, see comment above */
+
+
+/*** parameter allocation mode ***/
+
+int reg_parammode = PARAMMODE_NUMBERED;  
+
+   /* parameter-registers will be allocated by assigning the
+      1. parameter:   int/float-reg 16
+      2. parameter:   int/float-reg 17  
+      3. parameter:   int/float-reg 18 ....
+   */
+
+
+/************************** stackframe-infos **********************************/
+
+int localvars_base;  /* offset in stackframe for the local variables          */
+int savedregs_base;  /* offset in stackframe for the save area                */
+int parentargs_base; /* offset in stackframe for the parameter from the caller*/
+
+/* -> see file 'calling.doc' */
+
+
+/******************** macros to create code ***********************************/
+
+/* 3-address-operations: M_OP3
+      op ..... opcode
+      fu ..... function-number
+      a  ..... register number source 1
+      b  ..... register number or constant integer source 2
+      c  ..... register number destination
+      const .. switch to use b as constant integer 
+                 (0 means: use b as register number)
+                 (1 means: use b as constant 8-bit-integer)
+*/      
+#define M_OP3(op,fu,a,b,c,const) \
+       mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+       ((const)<<12)|((fu)<<5)|((c)) )
+
+/* 3-address-floating-point-operation: M_FOP3 
+     op .... opcode
+     fu .... function-number
+     a,b ... source floating-point registers
+     c ..... destination register
+*/ 
+#define M_FOP3(op,fu,a,b,c) \
+       mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+
+/* branch instructions: M_BRA 
+      op ..... opcode
+      a ...... register to be tested
+      disp ... relative address to be jumped to (divided by 4)
+*/
+#define M_BRA(op,a,disp) \
+       mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+
+
+/* memory operations: M_MEM
+      op ..... opcode
+      a ...... source/target register for memory access
+      b ...... base register
+      disp ... displacement (16 bit signed) to be added to b
+*/ 
+#define M_MEM(op,a,b,disp) \
+       mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/***** macros for all used commands (see an Alpha-manual for description) *****/ 
+
+#define M_LDA(a,b,disp)         M_MEM (0x08,a,b,disp)           /* low const  */
+#define M_LDAH(a,b,disp)        M_MEM (0x09,a,b,disp)           /* high const */
+#define M_BLDU(a,b,disp)        M_MEM (0x0a,a,b,disp)           /*  8 load    */
+#define M_SLDU(a,b,disp)        M_MEM (0x0c,a,b,disp)           /* 16 load    */
+#define M_ILD(a,b,disp)         M_MEM (0x28,a,b,disp)           /* 32 load    */
+#define M_LLD(a,b,disp)         M_MEM (0x29,a,b,disp)           /* 64 load    */
+#define M_BST(a,b,disp)         M_MEM (0x0e,a,b,disp)           /*  8 store   */
+#define M_SST(a,b,disp)         M_MEM (0x0d,a,b,disp)           /* 16 store   */
+#define M_IST(a,b,disp)         M_MEM (0x2c,a,b,disp)           /* 32 store   */
+#define M_LST(a,b,disp)         M_MEM (0x2d,a,b,disp)           /* 64 store   */
+
+#define M_BSEXT(b,c)            M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /*  8 signext */
+#define M_SSEXT(b,c)            M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
+
+#define M_BR(disp)              M_BRA (0x30,REG_ZERO,disp)      /* branch     */
+#define M_BSR(ra,disp)          M_BRA (0x34,ra,disp)            /* branch sbr */
+#define M_BEQZ(a,disp)          M_BRA (0x39,a,disp)             /* br a == 0  */
+#define M_BLTZ(a,disp)          M_BRA (0x3a,a,disp)             /* br a <  0  */
+#define M_BLEZ(a,disp)          M_BRA (0x3b,a,disp)             /* br a <= 0  */
+#define M_BNEZ(a,disp)          M_BRA (0x3d,a,disp)             /* br a != 0  */
+#define M_BGEZ(a,disp)          M_BRA (0x3e,a,disp)             /* br a >= 0  */
+#define M_BGTZ(a,disp)          M_BRA (0x3f,a,disp)             /* br a >  0  */
+
+#define M_JMP(a,b)              M_MEM (0x1a,a,b,0x0000)         /* jump       */
+#define M_JSR(a,b)              M_MEM (0x1a,a,b,0x4000)         /* call sbr   */
+#define M_RET(a,b)              M_MEM (0x1a,a,b,0x8000)         /* return     */
+
+#define M_IADD(a,b,c,const)     M_OP3 (0x10,0x0,  a,b,c,const)  /* 32 add     */
+#define M_LADD(a,b,c,const)     M_OP3 (0x10,0x20, a,b,c,const)  /* 64 add     */
+#define M_ISUB(a,b,c,const)     M_OP3 (0x10,0x09, a,b,c,const)  /* 32 sub     */
+#define M_LSUB(a,b,c,const)     M_OP3 (0x10,0x29, a,b,c,const)  /* 64 sub     */
+#define M_IMUL(a,b,c,const)     M_OP3 (0x13,0x00, a,b,c,const)  /* 32 mul     */
+#define M_LMUL(a,b,c,const)     M_OP3 (0x13,0x20, a,b,c,const)  /* 64 mul     */
+
+#define M_CMPEQ(a,b,c,const)    M_OP3 (0x10,0x2d, a,b,c,const)  /* c = a == b */
+#define M_CMPLT(a,b,c,const)    M_OP3 (0x10,0x4d, a,b,c,const)  /* c = a <  b */
+#define M_CMPLE(a,b,c,const)    M_OP3 (0x10,0x6d, a,b,c,const)  /* c = a <= b */
+
+#define M_CMPULE(a,b,c,const)   M_OP3 (0x10,0x3d, a,b,c,const)  /* c = a <= b */
+
+#define M_AND(a,b,c,const)      M_OP3 (0x11,0x00, a,b,c,const)  /* c = a &  b */
+#define M_OR(a,b,c,const)       M_OP3 (0x11,0x20, a,b,c,const)  /* c = a |  b */
+#define M_XOR(a,b,c,const)      M_OP3 (0x11,0x40, a,b,c,const)  /* c = a ^  b */
+
+#define M_SLL(a,b,c,const)      M_OP3 (0x12,0x39, a,b,c,const)  /* c = a << b */
+#define M_SRA(a,b,c,const)      M_OP3 (0x12,0x3c, a,b,c,const)  /* c = a >> b */
+#define M_SRL(a,b,c,const)      M_OP3 (0x12,0x34, a,b,c,const)  /* c = a >>>b */
+
+#define M_FLD(a,b,disp)         M_MEM (0x22,a,b,disp)           /* load flt   */
+#define M_DLD(a,b,disp)         M_MEM (0x23,a,b,disp)           /* load dbl   */
+#define M_FST(a,b,disp)         M_MEM (0x26,a,b,disp)           /* store flt  */
+#define M_DST(a,b,disp)         M_MEM (0x27,a,b,disp)           /* store dbl  */
+
+#define M_FADD(a,b,c)           M_FOP3 (0x16, 0x080, a,b,c)     /* flt add    */
+#define M_DADD(a,b,c)           M_FOP3 (0x16, 0x0a0, a,b,c)     /* dbl add    */
+#define M_FSUB(a,b,c)           M_FOP3 (0x16, 0x081, a,b,c)     /* flt sub    */
+#define M_DSUB(a,b,c)           M_FOP3 (0x16, 0x0a1, a,b,c)     /* dbl sub    */
+#define M_FMUL(a,b,c)           M_FOP3 (0x16, 0x082, a,b,c)     /* flt mul    */
+#define M_DMUL(a,b,c)           M_FOP3 (0x16, 0x0a2, a,b,c)     /* dbl mul    */
+#define M_FDIV(a,b,c)           M_FOP3 (0x16, 0x083, a,b,c)     /* flt div    */
+#define M_DDIV(a,b,c)           M_FOP3 (0x16, 0x0a3, a,b,c)     /* dbl div    */
+
+#define M_CVTLF(a,b,c)          M_FOP3 (0x16, 0x0bc, a,b,c)     /* long2flt   */
+#define M_CVTLD(a,b,c)          M_FOP3 (0x16, 0x0be, a,b,c)     /* long2dbl   */
+#define M_CVTDL(a,b,c)          M_FOP3 (0x16, 0x0af, a,b,c)     /* dbl2long   */
+#define M_CVTDL_C(a,b,c)        M_FOP3 (0x16, 0x02f, a,b,c)     /* dbl2long   */
+
+#define M_FCMPEQ(a,b,c)         M_FOP3 (0x16, 0x0a5, a,b,c)     /* c = a==b   */
+#define M_FCMPLT(a,b,c)         M_FOP3 (0x16, 0x0a6, a,b,c)     /* c = a<b    */
+
+#define M_FMOV(fa,fb)           M_FOP3 (0x17, 0x020, fa,fa,fb)  /* b = a      */
+#define M_FMOVN(fa,fb)          M_FOP3 (0x17, 0x021, fa,fa,fb)  /* b = -a     */
+
+#define M_FBEQZ(fa,disp)        M_BRA (0x31,fa,disp)            /* br a == 0.0*/
+
+/****** macros for special commands (see an Alpha-manual for description) *****/ 
+
+#define M_S4ADDL(a,b,c,const)   M_OP3 (0x10,0x02, a,b,c,const) /* c = a*4 + b */
+#define M_S4ADDQ(a,b,c,const)   M_OP3 (0x10,0x22, a,b,c,const) /* c = a*4 + b */
+#define M_S4SUBL(a,b,c,const)   M_OP3 (0x10,0x0b, a,b,c,const) /* c = a*4 - b */
+#define M_S4SUBQ(a,b,c,const)   M_OP3 (0x10,0x2b, a,b,c,const) /* c = a*4 - b */
+#define M_S8ADDL(a,b,c,const)   M_OP3 (0x10,0x12, a,b,c,const) /* c = a*8 + b */
+#define M_S8ADDQ(a,b,c,const)   M_OP3 (0x10,0x32, a,b,c,const) /* c = a*8 + b */
+#define M_S8SUBL(a,b,c,const)   M_OP3 (0x10,0x1b, a,b,c,const) /* c = a*8 - b */
+#define M_S8SUBQ(a,b,c,const)   M_OP3 (0x10,0x3b, a,b,c,const) /* c = a*8 - b */
+
+#define M_LLD_U(a,b,disp)       M_MEM (0x0b,a,b,disp)          /* unalign ld  */
+#define M_LST_U(a,b,disp)       M_MEM (0x0f,a,b,disp)          /* unalign st  */
+
+#define M_ZAP(a,b,c,const)      M_OP3 (0x12,0x30, a,b,c,const)
+#define M_ZAPNOT(a,b,c,const)   M_OP3 (0x12,0x31, a,b,c,const)
+#define M_EXTBL(a,b,c,const)    M_OP3 (0x12,0x06, a,b,c,const)
+#define M_EXTWL(a,b,c,const)    M_OP3 (0x12,0x16, a,b,c,const)
+#define M_EXTLL(a,b,c,const)    M_OP3 (0x12,0x26, a,b,c,const)
+#define M_EXTQL(a,b,c,const)    M_OP3 (0x12,0x36, a,b,c,const)
+#define M_EXTWH(a,b,c,const)    M_OP3 (0x12,0x5a, a,b,c,const)
+#define M_EXTLH(a,b,c,const)    M_OP3 (0x12,0x6a, a,b,c,const)
+#define M_EXTQH(a,b,c,const)    M_OP3 (0x12,0x7a, a,b,c,const)
+#define M_INSBL(a,b,c,const)    M_OP3 (0x12,0x0b, a,b,c,const)
+#define M_INSWL(a,b,c,const)    M_OP3 (0x12,0x1b, a,b,c,const)
+#define M_INSLL(a,b,c,const)    M_OP3 (0x12,0x2b, a,b,c,const)
+#define M_INSQL(a,b,c,const)    M_OP3 (0x12,0x3b, a,b,c,const)
+#define M_INSWH(a,b,c,const)    M_OP3 (0x12,0x57, a,b,c,const)
+#define M_INSLH(a,b,c,const)    M_OP3 (0x12,0x67, a,b,c,const)
+#define M_INSQH(a,b,c,const)    M_OP3 (0x12,0x77, a,b,c,const)
+#define M_MSKBL(a,b,c,const)    M_OP3 (0x12,0x02, a,b,c,const)
+#define M_MSKWL(a,b,c,const)    M_OP3 (0x12,0x12, a,b,c,const)
+#define M_MSKLL(a,b,c,const)    M_OP3 (0x12,0x22, a,b,c,const)
+#define M_MSKQL(a,b,c,const)    M_OP3 (0x12,0x32, a,b,c,const)
+#define M_MSKWH(a,b,c,const)    M_OP3 (0x12,0x52, a,b,c,const)
+#define M_MSKLH(a,b,c,const)    M_OP3 (0x12,0x62, a,b,c,const)
+#define M_MSKQH(a,b,c,const)    M_OP3 (0x12,0x72, a,b,c,const)
+
+
+/****** macros for unused commands (see an Alpha-manual for description) ******/ 
+
+#define M_ANDNOT(a,b,c,const)   M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b  */
+#define M_ORNOT(a,b,c,const)    M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b  */
+#define M_XORNOT(a,b,c,const)   M_OP3 (0x11,0x48, a,b,c,const) /* c = a ^~ b  */
+
+#define M_CMOVEQ(a,b,c,const)   M_OP3 (0x11,0x24, a,b,c,const) /* a==0 ? c=b  */
+#define M_CMOVNE(a,b,c,const)   M_OP3 (0x11,0x26, a,b,c,const) /* a!=0 ? c=b  */
+#define M_CMOVLT(a,b,c,const)   M_OP3 (0x11,0x44, a,b,c,const) /* a< 0 ? c=b  */
+#define M_CMOVGE(a,b,c,const)   M_OP3 (0x11,0x46, a,b,c,const) /* a>=0 ? c=b  */
+#define M_CMOVLE(a,b,c,const)   M_OP3 (0x11,0x64, a,b,c,const) /* a<=0 ? c=b  */
+#define M_CMOVGT(a,b,c,const)   M_OP3 (0x11,0x66, a,b,c,const) /* a> 0 ? c=b  */
+
+#define M_CMPULT(a,b,c,const)   M_OP3 (0x10,0x1d, a,b,c,const)
+#define M_CMPBGE(a,b,c,const)   M_OP3 (0x10,0x0f, a,b,c,const)
+
+#define M_FCMPUN(a,b,c)         M_FOP3 (0x16, 0x0a4, a,b,c)    /* unordered   */
+#define M_FCMPLE(a,b,c)         M_FOP3 (0x16, 0x0a7, a,b,c)    /* c = a<=b    */
+
+#define M_FBNEZ(fa,disp)        M_BRA (0x35,fa,disp)
+#define M_FBLEZ(fa,disp)        M_BRA (0x33,fa,disp)
+
+#define M_JMP_CO(a,b)           M_MEM (0x1a,a,b,0xc000)        /* call cosub  */
+
+
+/******************** system independent macros *******************************/
+
+
+/************** additional functions to generate code *************************/
+
+
+/* M_INTMOVE:
+     generates an integer-move from register a to b.
+     if a and b are the same int-register, no code will be generated.
+*/ 
+
+static void M_INTMOVE(int a, int b)
+{
+       if (a == b) return;
+       M_OR (a,a,b, 0);
+}
+
+
+/* M_FLTMOVE:
+    generates a floating-point-move from register a to b.
+    if a and b are the same float-register, no code will be generated
+*/ 
+
+static void M_FLTMOVE(int a, int b)
+{
+       if (a == b) return;
+       M_FMOV (a, b);
+}
+
+
+/* var_to_reg_xxx:
+    this function generates code to fetch data from a pseudo-register
+    into a real register. 
+    If the pseudo-register has actually been assigned to a real 
+    register, no code will be emitted, since following operations
+    can use this register directly.
+    
+    v: pseudoregister to be fetched from
+    tempregnum: temporary register to be used if v is actually spilled to ram
+
+    return: the register number, where the operand can be found after 
+            fetching (this wil be either tempregnum or the register
+            number allready given to v)
+*/
+
+static int var_to_reg_int (varid v, int tempregnum)
+{
+       reginfo *ri = v->reg;
+
+       if (!(ri->typeflags & REG_INMEMORY))
+               return ri->num;
+#ifdef STATISTICS
+       count_spills++;
+#endif
+       M_LLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+       return tempregnum;
+}
+
+
+static int var_to_reg_flt (varid v, int tempregnum)
+{
+       reginfo *ri = v->reg;
+
+
+       if (!(ri->typeflags & REG_INMEMORY))
+               return ri->num;
+#ifdef STATISTICS
+       count_spills++;
+#endif
+       M_DLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+       return tempregnum;
+}
+
+
+/* reg_of_var:
+     This function determines a register, to which the result of an
+     operation should go, when it is ultimatively intended to store the result
+     in pseudoregister v.
+     If v is assigned to an actual register, this register will be
+     returned.
+     Otherwise (when v is spilled) this function returns tempregnum.
+*/        
+
+static int reg_of_var(varid v, int tempregnum)
+{
+       if (!(v->reg->typeflags & REG_INMEMORY))
+               return v->reg->num;
+       return tempregnum;
+}
+
+
+/* store_reg_to_var_xxx:
+    This function generates the code to store the result of an operation
+    back into a spilled pseudo-variable.
+    If the pseudo-variable has not been spilled in the first place, this 
+    function will generate nothing.
+    
+    v ............ Pseudovariable
+    tempregnum ... Number of the temporary registers as returned by
+                   reg_of_var.
+*/     
+
+static void store_reg_to_var_int (varid v, int tempregnum)
+{
+       reginfo *ri = v->reg;
+
+       if (!(ri->typeflags & REG_INMEMORY))
+               return;
+#ifdef STATISTICS
+       count_spills++;
+#endif
+       M_LST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+}
+
+static void store_reg_to_var_flt (varid v, int tempregnum)
+{
+       reginfo *ri = v->reg;
+
+       if (!(ri->typeflags & REG_INMEMORY))
+               return;
+#ifdef STATISTICS
+       count_spills++;
+#endif
+       M_DST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
+}
+
+
+/***************** functions to process the pseudo commands *******************/
+
+/* gen_method:
+    function to generate method-call
+*/
+
+static void gen_method (pcmd *c)
+{
+       int p, pa, r;
+       s4  a;
+       reginfo *ri;
+       classinfo *ci;
+       
+       for (p = 0; p < c->u.method.paramnum; p++) {
+               ri = c->u.method.params[p]->reg;
+
+               if (p < INT_ARG_CNT) {            /* arguments that go into registers */
+                       if (IS_INT_LNG_REG(ri->typeflags)) {
+                               if (!(ri->typeflags & REG_INMEMORY))
+                                       M_INTMOVE(ri->num, INT_ARG_FST+p);
+                               else
+                                       M_LLD(INT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
+                               }
+                       else {
+                               if (!(ri->typeflags & REG_INMEMORY))
+                                       M_FLTMOVE (ri->num, FLT_ARG_FST+p);
+                               else
+                                       M_DLD(FLT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
+                               }
+                       }
+               else {                             /* arguments that go into memory   */
+                       pa = p - INT_ARG_CNT;
+                       if (pa >= arguments_num)
+                               panic ("invalid stackframe structure");
+                       
+                       if (IS_INT_LNG_REG(ri->typeflags)) {
+                               r = var_to_reg_int (c->u.method.params[p], REG_ITMP1);
+                               M_LST(r, REG_SP, 8 * (0 + pa));
+                               }
+                       else {
+                               r = var_to_reg_flt (c->u.method.params[p], REG_FTMP1);
+                               M_DST (r, REG_SP, 8 * (0 + pa));
+                               }
+                       }
+               }  /* end of for */
+
+       switch (c->opcode) {
+               case CMD_BUILTIN:
+                       a = dseg_addaddress ( (void*) (c->u.method.builtin) );
+
+                       M_LLD (REG_PV, REG_PV, a);        /* Pointer to built-in-function */
+                       goto makeactualcall;
+
+               case CMD_INVOKESTATIC:
+               case CMD_INVOKESPECIAL:
+                       a = dseg_addaddress ( c->u.method.method->stubroutine );
+
+                       M_LLD (REG_PV, REG_PV, a );              /* Method-Pointer in r27 */
+
+                       goto makeactualcall;
+
+               case CMD_INVOKEVIRTUAL:
+
+                       M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));
+                       M_LLD (REG_PV, REG_METHODPTR,
+                          OFFSET(vftbl,table[0]) + 
+                          sizeof(methodptr) * c->u.method.method->vftblindex );
+
+                       goto makeactualcall;
+
+               case CMD_INVOKEINTERFACE:
+                       ci = c->u.method.method->class;
+                       
+                       M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));    
+                       M_LLD (REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl, interfacevftbl));
+                       M_LLD (REG_METHODPTR, REG_METHODPTR, sizeof(methodptr*) * ci->index);
+                       M_LLD (REG_PV, REG_METHODPTR, sizeof(methodptr) * (c->u.method.method - ci->methods) );
+
+                       goto makeactualcall;
+
+               default:
+                       sprintf (logtext, "Unkown PCMD-Command: %d", c->opcode);
+                       error ();
+               }
+
+
+makeactualcall:
+
+
+       M_JSR (REG_RA, REG_PV);
+       if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+       else {
+               s4 ml=-mcodelen, mh=0;
+               while (ml<-32768) { ml+=65536; mh--; }
+               M_LDA (REG_PV, REG_RA, ml );
+               M_LDAH (REG_PV, REG_PV, mh );
+       }
+       
+       if ( c->dest ) {
+               ri = c->dest->reg;
+
+               if (IS_INT_LNG_REG(ri->typeflags)) {
+                       if (!(ri->typeflags & REG_INMEMORY))
+                               M_INTMOVE (REG_RESULT, ri->num);
+                       else  M_LST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
+                       }
+               else {
+                       if (!(ri->typeflags & REG_INMEMORY))
+                               M_FLTMOVE (REG_RESULT, ri->num);
+                       else  M_DST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
+                       }
+               }
+
+       if (c->u.method.exceptionvar) {
+               ri = c->u.method.exceptionvar->reg;
+               if (!(ri->typeflags & REG_INMEMORY))
+                       M_INTMOVE (REG_EXCEPTION, ri->num);     
+               else M_LST (REG_EXCEPTION, REG_SP, 8 *(localvars_base + ri->num) );
+               }
+}
+
+
+/************************ function block_genmcode ******************************
+
+       generates machine code for a complete basic block
+
+*******************************************************************************/
+
+
+static void block_genmcode(basicblock *b)
+{
+       int  s1, s2, s3, d;
+       s4   a;
+       pcmd *c;
+                       
+       mcode_blockstart (b);
+
+       for(c = list_first(&(b->pcmdlist));
+           c != NULL;
+           c = list_next(&(b->pcmdlist), c))
+
+       switch (c->opcode) {
+
+               case CMD_TRACEBUILT:
+                       M_LDA (REG_SP, REG_SP, -8);
+                       a = dseg_addaddress (c->u.a.value);
+                       M_LLD(REG_ITMP1, REG_PV, a);
+                       M_LST(REG_ITMP1, REG_SP, 0);
+                       a = dseg_addaddress ((void*) (builtin_trace_args));
+                       M_LLD(REG_PV, REG_PV, a);
+                       M_JSR (REG_RA, REG_PV);
+                       if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+                       else {
+                               s4 ml=-mcodelen, mh=0;
+                               while (ml<-32768) { ml+=65536; mh--; }
+                               M_LDA (REG_PV, REG_RA, ml );
+                               M_LDAH (REG_PV, REG_PV, mh );
+                               }
+                       M_LDA (REG_SP, REG_SP, 8);
+                       b -> mpc = mcodelen;
+                       break;
+
+
+               /*********************** constant operations **************************/
+
+               case CMD_LOADCONST_I:
+                       d = reg_of_var(c->dest, REG_ITMP1);
+                       if ( (c->u.i.value >= -32768) && (c->u.i.value <= 32767) ) {
+                               M_LDA (d, REG_ZERO, c->u.i.value);
+                               } 
+                       else {
+                               a = dseg_adds4 (c->u.i.value);
+                               M_ILD (d, REG_PV, a);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LOADCONST_L:
+                       d = reg_of_var(c->dest, REG_ITMP1);
+#if U8_AVAILABLE
+                       if ((c->u.l.value >= -32768) && (c->u.l.value <= 32767) ) {
+                               M_LDA (d, REG_ZERO, c->u.l.value);
+                               } 
+                       else {
+                               a = dseg_adds8 (c->u.l.value);
+                               M_LLD (d, REG_PV, a);
+                               }
+#else
+                       a = dseg_adds8 (c->u.l.value);
+                       M_LLD (d, REG_PV, a);
+#endif
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LOADCONST_F:
+                       d = reg_of_var (c->dest, REG_FTMP1);
+                       a = dseg_addfloat (c->u.f.value);
+                       M_FLD (d, REG_PV, a);
+                       store_reg_to_var_flt (c->dest, d);
+                       break;
+                       
+               case CMD_LOADCONST_D:
+                       d = reg_of_var (c->dest, REG_FTMP1);
+                       a = dseg_adddouble (c->u.d.value);
+                       M_DLD (d, REG_PV, a);
+                       store_reg_to_var_flt (c->dest, d);
+                       break;
+
+
+               case CMD_LOADCONST_A:
+                       d = reg_of_var(c->dest, REG_ITMP1);
+                       if (c->u.a.value) {
+                               a = dseg_addaddress (c->u.a.value);
+                               M_LLD (d, REG_PV, a);
+                               }
+                       else {
+                               M_INTMOVE (REG_ZERO, d);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               /************************* move operation *****************************/
+
+               case CMD_MOVE:
+                       if (IS_INT_LNG_REG(c->source1->reg->typeflags)) {
+                               d = reg_of_var(c->dest, REG_ITMP1);
+                               s1 = var_to_reg_int(c->source1, d);
+                               M_INTMOVE(s1,d);
+                               store_reg_to_var_int(c->dest, d);
+                               }
+                       else {
+                               d = reg_of_var(c->dest, REG_FTMP1);
+                               s1 = var_to_reg_flt(c->source1, d);
+                               M_FLTMOVE(s1,d);
+                               store_reg_to_var_flt(c->dest, d);
+                               }
+                       break;
+
+
+               /********************* integer operations *****************************/
+
+               case CMD_IINC:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1); 
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if ((c->u.i.value >= 0) && (c->u.i.value <= 256)) {
+                               M_IADD (s1, c->u.i.value, d, 1);
+                               }
+                       else if ((c->u.i.value >= -256) && (c->u.i.value < 0)) {
+                               M_ISUB (s1, (-c->u.i.value), d, 1);
+                               }
+                       else {
+                               M_LDA  (d, s1, c->u.i.value);
+                               M_IADD (d, REG_ZERO, d, 0);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_INEG:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1); 
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_ISUB (REG_ZERO, s1, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LNEG:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LSUB (REG_ZERO, s1, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_I2L:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_INTMOVE (s1, d);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_L2I:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_IADD (s1, REG_ZERO, d , 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_INT2BYTE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_BSEXT  (s1, d);
+                               }
+                       else {
+                               M_SLL (s1,56, d, 1);
+                               M_SRA ( d,56, d, 1);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_INT2CHAR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+            M_ZAPNOT (s1, 0x03, d, 1);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_INT2SHORT:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_SSEXT  (s1, d);
+                               }
+                       else {
+                               M_SLL ( s1, 48, d, 1);
+                               M_SRA (  d, 48, d, 1);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IADD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_IADD (s1, s2, d,  0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_LADD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LADD (s1, s2, d,  0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_ISUB:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_ISUB (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_LSUB:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LSUB (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IMUL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_IMUL (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_LMUL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LMUL (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+                   
+               case CMD_ISHL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_AND (s2, 0x1f, REG_ITMP3, 1);
+                       M_SLL (s1, REG_ITMP3, d, 0);
+                       M_IADD (d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_ISHR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_AND (s2, 0x1f, REG_ITMP3,  1);
+                       M_SRA (s1, REG_ITMP3, d,   0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IUSHR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_AND    (s2, 0x1f, REG_ITMP2,  1);
+            M_ZAPNOT (s1, 0x0f, d, 1);
+                       M_SRL    ( d, REG_ITMP2, d, 0);
+                       M_IADD   ( d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LSHL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_SLL (s1, s2, d,  0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LSHR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_SRA (s1, s2, d,  0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_LUSHR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_SRL (s1, s2, d,  0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IAND:
+               case CMD_LAND:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_AND (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IOR:
+               case CMD_LOR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_OR   ( s1,s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_IXOR:
+               case CMD_LXOR:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_XOR (s1, s2, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+
+               case CMD_LCMP:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_CMPLT  (s1, s2, REG_ITMP3, 0);
+                       M_CMPLT  (s2, s1, REG_ITMP1, 0);
+                       M_LSUB   (REG_ITMP1, REG_ITMP3, d, 0);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+                       
+
+               /*********************** floating operations **************************/
+
+               case CMD_FNEG:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FMOVN (s1, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DNEG:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FMOVN (s1, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+
+               case CMD_FADD:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FADD ( s1,s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DADD:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_DADD (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+
+               case CMD_FSUB:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FSUB (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DSUB:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_DSUB (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+
+               case CMD_FMUL:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FMUL   (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DMUL:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_DMUL   (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+
+               case CMD_FDIV:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FDIV   (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DDIV:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_DDIV   (s1, s2, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               
+               case CMD_FREM:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FDIV   ( s1,s2, REG_FTMP3 );
+                       M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
+                       M_CVTLF ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
+                       M_FMUL ( REG_FTMP3, s2, REG_FTMP3 );
+                       M_FSUB ( s1, REG_FTMP3, d);
+                       store_reg_to_var_flt(c->dest, d);
+                   break;
+               case CMD_DREM:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_DDIV   ( s1,s2, REG_FTMP3 );
+                       M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
+                       M_CVTLD ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
+                       M_DMUL ( REG_FTMP3, s2, REG_FTMP3 );
+                       M_DSUB ( s1, REG_FTMP3, d);
+                       store_reg_to_var_flt(c->dest, d);
+                   break;
+
+               case CMD_I2F:
+               case CMD_L2F:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       a = dseg_adddouble(0.0);
+                       M_LST (s1, REG_PV, a);
+                       M_DLD (d, REG_PV, a);
+                       M_CVTLF ( REG_ZERO, d, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+
+               case CMD_I2D:
+               case CMD_L2D:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       a = dseg_adddouble(0.0);
+                       M_LST (s1, REG_PV, a);
+                       M_DLD (d, REG_PV, a);
+                       M_CVTLD ( REG_ZERO, d, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+                       
+               case CMD_F2I:
+               case CMD_D2I:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       a = dseg_adddouble(0.0);
+                       M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
+                       M_DST (REG_FTMP1, REG_PV, a);
+                       M_ILD (d, REG_PV, a);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               
+               case CMD_F2L:
+               case CMD_D2L:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       a = dseg_adddouble(0.0);
+                       M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
+                       M_DST (REG_FTMP1, REG_PV, a);
+                       M_LLD (d, REG_PV, a);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_F2D:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FLTMOVE (s1, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+                                       
+               case CMD_D2F:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_FADD (s1, REG_ZERO, d);
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               
+               case CMD_FCMPL:
+               case CMD_DCMPL:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LSUB   (REG_ZERO, 1, d, 1);
+                       M_FCMPEQ (s1, s2, REG_FTMP3);
+                       M_FBEQZ  (REG_FTMP3, 1);   /* jump over next instructions         */
+                       M_OR     (REG_ZERO, REG_ZERO, d, 0);
+                       M_FCMPLT (s2, s1, REG_FTMP3);
+                       M_FBEQZ  (REG_FTMP3, 1);   /* jump over next instruction          */
+                       M_LADD   (REG_ZERO, 1, d, 1);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+                       
+               case CMD_FCMPG:
+               case CMD_DCMPG:
+                       s1 = var_to_reg_flt(c->source1, REG_FTMP1);
+                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_LADD   (REG_ZERO, 1, d, 1);
+                       M_FCMPEQ (s1, s2, REG_FTMP3);
+                       M_FBEQZ  (REG_FTMP3, 1);   /* jump over next instruction          */
+                       M_OR     (REG_ZERO, REG_ZERO, d, 0);
+                       M_FCMPLT (s1, s2, REG_FTMP3);
+                       M_FBEQZ  (REG_FTMP3, 1);   /* jump over next instruction          */
+                       M_LSUB   (REG_ZERO, 1, d, 1);
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+
+               /********************** memory operations *****************************/
+
+               case CMD_ARRAYLENGTH:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_ILD    (d, s1, OFFSET(java_arrayheader, size));
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_AALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_LLD    ( d, REG_ITMP1, OFFSET (java_objectarray, data[0]));
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_LALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_LLD    ( d, REG_ITMP1, OFFSET (java_longarray, data[0]));
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_IALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_ILD    ( d, REG_ITMP1, OFFSET (java_intarray, data[0]));
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_FALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_FLD    ( d, REG_ITMP1, OFFSET (java_floatarray, data[0]));
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_DALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_FTMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_DLD    ( d, REG_ITMP1, OFFSET (java_doublearray, data[0]));
+                       store_reg_to_var_flt(c->dest, d);
+                       break;
+               case CMD_CALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SLDU   (d, REG_ITMP1, OFFSET (java_chararray, data[0]));
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1,  0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_EXTWL  (REG_ITMP2, REG_ITMP1, d, 0);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;                  
+               case CMD_SALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SLDU   (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+                               M_SSEXT  (d, d);
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1,  0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]) + 2);
+                               M_EXTQH  (REG_ITMP2, REG_ITMP1, d, 0);
+                               M_SRA    (d, 48, d, 1);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+               case CMD_BALOAD:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       d = reg_of_var(c->dest, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_BLDU   (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+                               M_BSEXT  (d, d);
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1,  0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]) + 1);
+                               M_EXTQH  (REG_ITMP2, REG_ITMP1, d,   0);
+                               M_SRA    (d, 56, d,  1);
+                               }
+                       store_reg_to_var_int(c->dest, d);
+                       break;
+
+               case CMD_AASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_LST    (s3, REG_ITMP1, OFFSET (java_objectarray, data[0]));
+                       break;
+               case CMD_LASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_LST    (s3, REG_ITMP1, OFFSET (java_longarray, data[0]));
+                       break;
+               case CMD_IASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_IST    (s3, REG_ITMP1, OFFSET (java_intarray, data[0]));
+                       break;
+               case CMD_FASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_flt(c->source3, REG_FTMP3);
+                       M_S4ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_FST    (s3, REG_ITMP1, OFFSET (java_floatarray, data[0]));
+                       break;
+               case CMD_DASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_flt(c->source3, REG_FTMP3);
+                       M_S8ADDQ (s2, s1, REG_ITMP1, 0);
+                       M_DST    (s3, REG_ITMP1, OFFSET (java_doublearray, data[0]));
+                       break;
+               case CMD_CASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SST    (s3, REG_ITMP1, OFFSET (java_chararray, data[0]));
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_INSWL  (s3, REG_ITMP1, REG_ITMP3, 0);
+                               M_MSKWL  (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+                               M_OR     (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+                               M_LST_U  (REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+               case CMD_SASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SST    (s3, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_LADD   (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_INSWL  (s3, REG_ITMP1, REG_ITMP3, 0);
+                               M_MSKWL  (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+                               M_OR     (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+                               M_LST_U  (REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+               case CMD_BASTORE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       s3 = var_to_reg_int(c->source3, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_BST    (s3, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+                               }
+                       else {
+                               M_LADD   (s2, s1, REG_ITMP1,  0);
+                               M_LLD_U  (REG_ITMP2, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+                               M_LDA    (REG_ITMP1, REG_ITMP1, OFFSET (java_bytearray, data[0]));
+                               M_INSBL  (s3, REG_ITMP1, REG_ITMP3,     0);
+                               M_MSKBL  (REG_ITMP2, REG_ITMP1, REG_ITMP2,  0);
+                               M_OR     (REG_ITMP2, REG_ITMP3, REG_ITMP2,  0);
+                               M_LST_U  (REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+
+
+               case CMD_PUTFIELD:
+                       switch (c->u.mem.type) {
+                               case TYPE_INT:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                                       M_IST (s2, s1, c->u.mem.offset);
+                                       break;
+                               case TYPE_LONG:
+                               case TYPE_ADDRESS:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                                       M_LST (s2, s1, c->u.mem.offset);
+                                       break;
+                               case TYPE_FLOAT:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                                       M_FST (s2, s1, c->u.mem.offset);
+                                       break;
+                               case TYPE_DOUBLE:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       s2 = var_to_reg_flt(c->source2, REG_FTMP2);
+                                       M_DST (s2, s1, c->u.mem.offset);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+               case CMD_GETFIELD:
+                       switch (c->u.mem.type) {
+                               case TYPE_INT:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       d = reg_of_var(c->dest, REG_ITMP3);
+                                       M_ILD (d, s1, c->u.mem.offset);
+                                       store_reg_to_var_int(c->dest, d);
+                                       break;
+                               case TYPE_LONG:
+                               case TYPE_ADDRESS:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       d = reg_of_var(c->dest, REG_ITMP3);
+                                       M_LLD (d, s1, c->u.mem.offset);
+                                       store_reg_to_var_int(c->dest, d);
+                                       break;
+                               case TYPE_FLOAT:
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       d = reg_of_var(c->dest, REG_FTMP1);
+                                       M_FLD (d, s1, c->u.mem.offset);
+                                       store_reg_to_var_flt(c->dest, d);
+                                       break;
+                               case TYPE_DOUBLE:                               
+                                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                                       d = reg_of_var(c->dest, REG_FTMP1);
+                                       M_DLD (d, s1, c->u.mem.offset);
+                                       store_reg_to_var_flt(c->dest, d);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+
+               /********************** branch operations *****************************/
+
+               case CMD_GOTO:
+                       mcode_addreference (c->u.bra.target);
+                       M_BR (0);
+                       break;
+
+               case CMD_JSR: {
+                       reginfo *di = c->dest->reg;
+
+                       if (di->typeflags & REG_INMEMORY)
+                               panic ("Can not put returnaddress into memory var");
+
+                       mcode_addreference (c->u.bra.target);
+                       M_BSR (di->num, 0);
+                       }
+                       break;
+                       
+               case CMD_RET:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       M_RET (REG_ZERO, s1);
+                       break;
+
+               case CMD_IFEQ:
+               case CMD_IFEQL:
+               case CMD_IFNULL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BEQZ (s1, 0);
+                       break;
+               case CMD_IFLT:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BLTZ (s1, 0);
+                       break;
+               case CMD_IFLE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BLEZ (s1, 0);
+                       break;
+               case CMD_IFNE:
+               case CMD_IFNONNULL:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BNEZ (s1, 0);
+                       break;
+               case CMD_IFGT:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BGTZ (s1, 0);
+                       break;
+               case CMD_IFGE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       mcode_addreference (c->u.bra.target);
+                       M_BGEZ (s1, 0);
+                       break;
+
+               case CMD_IF_ICMPEQ:
+               case CMD_IF_ACMPEQ:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPEQ (s1, s2, REG_ITMP1, 0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BNEZ (REG_ITMP1, 0);
+                       break;
+               case CMD_IF_ICMPNE:
+               case CMD_IF_ACMPNE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPEQ (s1, s2, REG_ITMP1, 0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BEQZ (REG_ITMP1, 0);
+                       break;
+               case CMD_IF_ICMPLT:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPLT (s1, s2, REG_ITMP1, 0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BNEZ (REG_ITMP1, 0);
+                       break;
+               case CMD_IF_ICMPGT:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPLE (s1, s2, REG_ITMP1, 0);
+                       mcode_addreference ( c->u.bra.target );
+                       M_BEQZ (REG_ITMP1, 0);
+                       break;
+               case CMD_IF_ICMPLE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPLE (s1, s2, REG_ITMP1, 0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BNEZ (REG_ITMP1, 0);
+                       break;
+               case CMD_IF_ICMPGE:
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPLT (s1, s2, REG_ITMP1,  0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BEQZ (REG_ITMP1, 0);
+                       break;
+
+               case CMD_IF_UCMPGE: /* branch if the unsigned value of s1 is 
+                                      greater that s2 (note, that s2 has
+                                      to be >= 0) */
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_CMPULE (s2, s1, REG_ITMP1, 0);
+                       mcode_addreference (c->u.bra.target);
+                       M_BNEZ (REG_ITMP1, 0);
+            break;
+
+
+               case CMD_IRETURN:
+               case CMD_LRETURN:
+               case CMD_ARETURN:
+                       s1 = var_to_reg_int(c->source1, REG_RESULT);
+                       M_INTMOVE (s1, REG_RESULT);
+                       goto nowperformreturn;
+               case CMD_FRETURN:
+               case CMD_DRETURN:
+                       s1 = var_to_reg_flt(c->source1, REG_FRESULT);
+                       M_FLTMOVE (s1, REG_FRESULT);
+                       goto nowperformreturn;
+
+               case CMD_RETURN:
+nowperformreturn:
+                       {
+                       int r, p;
+                       
+                       s2 = var_to_reg_int(c->source2, REG_ITMP2);
+                       M_INTMOVE (s2, REG_EXCEPTION);
+
+                       p = parentargs_base;
+                       if (!isleafmethod)
+                               {p--;  M_LLD (REG_RA, REG_SP, 8*p);}
+                       for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
+                               if (!(intregs[r].typeflags & REG_ISUNUSED))
+                                       {p--; M_LLD (r, REG_SP, 8*p);}
+                       for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
+                               if (!(floatregs[r].typeflags & REG_ISUNUSED))
+                                       {p--; M_DLD (r, REG_SP, 8*p);}
+
+                       if (parentargs_base)
+                               {M_LDA (REG_SP, REG_SP, parentargs_base*8);}
+                       if (runverbose) {
+                               M_LDA (REG_SP, REG_SP, -32);
+                               M_LST(REG_RA, REG_SP, 0);
+                               M_LST(REG_RESULT, REG_SP, 8);
+                               M_DST(REG_FRESULT, REG_SP,16);
+                               M_LST(REG_EXCEPTION, REG_SP, 24);
+                               a = dseg_addaddress (method);
+                               M_LLD(INT_ARG_FST, REG_PV, a);
+                               M_OR(REG_RESULT, REG_RESULT, INT_ARG_FST + 1, 0);
+                               M_FLTMOVE(REG_FRESULT, FLT_ARG_FST + 2);
+                               a = dseg_addaddress ((void*) (builtin_displaymethodstop));
+                               M_LLD(REG_PV, REG_PV, a);
+                               M_JSR (REG_RA, REG_PV);
+                               if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
+                               else {
+                                       s4 ml=-mcodelen, mh=0;
+                                       while (ml<-32768) { ml+=65536; mh--; }
+                                       M_LDA (REG_PV, REG_RA, ml );
+                                       M_LDAH (REG_PV, REG_PV, mh );
+                                       }
+                               M_LLD(REG_EXCEPTION, REG_SP, 24);
+                               M_DLD(REG_FRESULT, REG_SP,16);
+                               M_LLD(REG_RESULT, REG_SP, 8);
+                               M_LLD(REG_RA, REG_SP, 0);
+                               M_LDA (REG_SP, REG_SP, 32);
+                               }
+                       M_RET (REG_ZERO, REG_RA);
+                       }
+                       break;
+
+
+               case CMD_TABLEJUMP:
+                       {
+                       int i;
+
+                       /* build jump table top down and use address of lowest entry */
+
+                       a = 0;
+                       for (i = c->u.tablejump.targetcount - 1; i >= 0; i--) {
+                               a = dseg_addtarget (c->u.tablejump.targets[i]);
+                               }
+                       }
+
+                       /* last offset a returned by dseg_addtarget is used by load */
+
+                       s1 = var_to_reg_int(c->source1, REG_ITMP1);
+                       M_S8ADDQ (s1, REG_PV, REG_ITMP2, 0);
+                       M_LLD (REG_ITMP3, REG_ITMP2, a);
+                       M_JMP (REG_ZERO, REG_ITMP3);
+                       break;
+
+
+               case CMD_INVOKESTATIC:
+               case CMD_INVOKESPECIAL:
+               case CMD_INVOKEVIRTUAL:
+               case CMD_INVOKEINTERFACE:
+               case CMD_BUILTIN:
+                       gen_method (c);
+                       break;
+
+               case CMD_DROP:
+               case CMD_ACTIVATE:
+                       break;
+
+               default: sprintf (logtext, "Unknown pseudo command: %d(%d)", c->opcode,
+                                 c->tag);
+                                error();
+       }
+}
+
+
+/*********************** function input_args_prealloc **************************
+
+       preallocates the input arguments (on the Alpha only for leaf methods)
+
+*******************************************************************************/
+
+
+static void input_args_prealloc()
+{
+       int     i, t;
+       varid   p;
+       reginfo *r;
+
+       if (isleafmethod)
+               for (i = 0; (i < mparamnum) && (i < INT_ARG_CNT); i++) {
+                       t = mparamtypes[i];
+                       p = mparamvars[i];
+                       p->saved = !isleafmethod;
+                       if (t==TYPE_DOUBLE || t==TYPE_FLOAT)
+                               r = &floatregs[FLT_ARG_FST + i];
+                       else
+                               r = &intregs[INT_ARG_FST + i];
+                       r->typeflags &= ~REG_ISFREEUNUSED;
+                       p->reg = r;
+                       }
+}
+
+
+/********************* function gen_computestackframe **************************
+
+       computes the size and the layout of a stack frame.
+       The values of localvars_base, savedregs_base, parentargs_base 
+    are numbers of 8-byte slots in the stackframe (every spilled or
+    saved register value will be stored in a 64-bit slot, regardless
+    of its type: INT/LONG/FLOAT/DOUBLE/ADDRESS)
+       (a detailed description of the stack frame is contained in 'calling.doc')
+
+
+*******************************************************************************/
+
+
+static void gen_computestackframe()
+{
+       int i;
+
+       savedregs_num = (isleafmethod) ? 0 : 1;   /* space to save the RA */
+
+       /* space to save used callee saved registers */
+
+       for (i = INT_SAV_FST; i < INT_SAV_FST + INT_SAV_CNT; i++)
+               if (! (intregs[i].typeflags & REG_ISUNUSED))
+                       savedregs_num++;
+       for (i = FLT_SAV_FST; i < FLT_SAV_FST + FLT_SAV_CNT; i++)
+               if (! (floatregs[i].typeflags & REG_ISUNUSED))
+                       savedregs_num++;
+
+       localvars_base = arguments_num;
+       savedregs_base = localvars_base + localvars_num;
+       parentargs_base = savedregs_base + savedregs_num;
+}
+
+
+/******************** function gen_header **************************************
+
+       using the data computed by gen_computestackframe it generates a function
+       header which:
+       
+               - saves the necessary registers
+               - copies arguments to registers or to stack slots
+               
+*******************************************************************************/
+
+
+static void gen_header ()
+{
+       int p, pa, r;
+       reginfo *ri;
+
+
+       /* create stack frame (if necessary) */
+
+       if (parentargs_base)
+               {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
+
+       /* save return address and used callee saved registers */
+
+       p = parentargs_base;
+       if (!isleafmethod)
+               {p--;  M_LST (REG_RA, REG_SP, 8*p);}
+       for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
+               if (!(intregs[r].typeflags & REG_ISUNUSED))
+                       {p--; M_LST (r, REG_SP, 8 * p);}
+       for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
+               if (!(floatregs[r].typeflags & REG_ISUNUSED))
+                       {p--; M_DST (r, REG_SP, 8 * p);}
+
+       /* take arguments out of register or stack frame */
+
+       for (p = 0; p < mparamnum; p++) {
+               ri = mparamvars[p]->reg;
+
+               if (p < INT_ARG_CNT) {                       /* register arguments    */
+                       if (IS_INT_LNG_REG(ri->typeflags)) {     /* integer args          */ 
+                               if (!(ri->typeflags & REG_INMEMORY)) /* reg arg -> register   */
+                                       M_INTMOVE (16+p, ri->num);
+                               else                                 /* reg arg -> spilled    */
+                                       M_LST (16+p, REG_SP, 8 * (localvars_base + ri->num));
+                               }
+                       else {                                   /* floating args         */   
+                               if (!(ri->typeflags & REG_INMEMORY)) /* reg-arg -> register   */
+                                       M_FLTMOVE (16+p, ri->num);
+                               else                                             /* reg-arg -> spilled    */
+                                       M_DST (16+p, REG_SP, 8 * (localvars_base + ri->num));
+                               }
+                       }
+
+               else {                                       /* stack arguments       */
+                       pa = p - INT_ARG_CNT;
+                       if (IS_INT_LNG_REG(ri->typeflags)) {     /* integer args          */
+                               if (!(ri->typeflags & REG_INMEMORY)) /* stack arg -> register */ 
+                                       M_LLD (ri->num, REG_SP, 8 * (parentargs_base + pa));
+                               else {                               /* stack arg -> spilled  */
+                                       M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
+                                       M_LST (REG_ITMP1, REG_SP, 8 * (localvars_base + ri->num));
+                                       }
+                               }
+                       else {
+                               if (!(ri->typeflags & REG_INMEMORY)) /* stack-arg -> register */
+                                       M_DLD (ri->num, REG_SP, 8 * (parentargs_base + pa) );
+                               else {                               /* stack-arg -> spilled  */
+                                       M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
+                                       M_DST (REG_FTMP1, REG_SP, 8 * (localvars_base + ri->num));
+                                       }
+                               }
+                       }
+               }  /* end for */
+}  /* end gen_header */
+
+
+/************************ function gen_resolvebranch ***************************
+
+       backpatches a branch instruction; Alpha branch instructions are very
+       regular, so it is only necessary to overwrite some fixed bits in the
+       instruction.
+
+       parameters: mcodepiece .. start of code area
+                   sourcepos ... offset of branch instruction
+                   targetpos ... offset of branch target
+
+*******************************************************************************/
+
+
+static void gen_resolvebranch ( void* mcodepiece, s4 sourcepos, s4 targetpos)
+{
+       s4 *command = mcodepiece;
+       s4 offset = targetpos - (sourcepos+4);
+
+       (*command) |=  ((offset >> 2) & ((s4) 0x1fffff) );
+}
+
+
+
+/******** redefinition of code generation makros (compilinf into array) *******/
+
+/* 
+These macros are newly defined to allow code generation into an array.
+This is necessary, because the original M_.. macros generate code by
+calling 'mcode_adds4' that uses an additional data structure to
+receive the code.
+
+For a faster (but less flexible) version to generate code, these
+macros directly use the (s4* p) - pointer to put the code directly
+in a locally defined array.
+This makes sense only for the stub-generation-routines below.
+*/
+
+#undef M_OP3
+#define M_OP3(op,fu,a,b,c,const) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+       ((const)<<12)|((fu)<<5)|((c)) )
+#undef M_FOP3
+#define M_FOP3(op,fu,a,b,c) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+#undef M_BRA
+#define M_BRA(op,a,disp) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+#undef M_MEM
+#define M_MEM(op,a,b,disp) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/************************ function createcompilerstub **************************
+
+       creates a stub routine which calls the compiler
+       
+*******************************************************************************/
+
+#define COMPSTUBSIZE 3
+
+u1 *createcompilerstub (methodinfo *m)
+{
+       u8 *s = CNEW (u8, COMPSTUBSIZE);    /* memory to hold the stub            */
+       s4 *p = (s4*) s;                    /* code generation pointer            */
+       
+                                           /* code for the stub                  */
+       M_LLD (REG_PV, REG_PV, 16);         /* load pointer to the compiler       */
+       M_JMP (0, REG_PV);                  /* jump to the compiler, return address
+                                              in reg 0 is used as method pointer */
+       s[1] = (u8) m;                      /* literals to be adressed            */  
+       s[2] = (u8) asm_call_jit_compiler;  /* jump directly via PV from above    */
+
+#ifdef STATISTICS
+       count_cstub_len += COMPSTUBSIZE * 8;
+#endif
+
+       return (u1*) s;
+}
+
+
+/************************* function removecompilerstub *************************
+
+     deletes a compilerstub from memory  (simply by freeing it)
+
+*******************************************************************************/
+
+void removecompilerstub (u1 *stub) 
+{
+       CFREE (stub, COMPSTUBSIZE * 8);
+}
+
+
+/********************* Funktion: createnativestub ******************************
+
+       creates a stub routine which calls a native method
+       
+*******************************************************************************/
+
+#define NATIVESTUBSIZE 11
+
+u1 *createnativestub (functionptr f, methodinfo *m)
+{
+       u8 *s = CNEW (u8, NATIVESTUBSIZE);  /* memory to hold the stub      */
+       s4 *p = (s4*) s;                    /* code generation pointer      */
+
+       M_LDA  (REG_SP, REG_SP, -8);        /* build up stackframe          */
+       M_LST  (REG_RA, REG_SP, 0);         /* store return address         */
+
+       M_LLD  (REG_PV, REG_PV, 6*8);       /* load adress of native method */
+       M_JSR  (REG_RA, REG_PV);            /* call native method           */
+       M_LDA  (REG_PV, REG_RA, -4*4);      /* recompute pv from ra         */
+
+       M_LLD  (22, REG_PV, 7*8);           /* get address of exceptionptr  */
+       M_LLD  (REG_EXCEPTION, 22, 0);      /* load exception into reg. 1   */
+       M_LST  (REG_ZERO, 22, 0);           /* store NULL into exceptionptr */
+
+       M_LLD  (REG_RA, REG_SP, 0);         /* load return address          */
+       M_LDA  (REG_SP, REG_SP, 8);         /* remove stackframe            */
+       
+       M_RET  (REG_ZERO, REG_RA);          /* return to caller             */
+
+       s[6] = (u8) f;                      /* address of native method     */
+       s[7] = (u8) (&exceptionptr);        /* address of exceptionptr      */
+
+#ifdef STATISTICS
+       count_nstub_len += NATIVESTUBSIZE * 8;
+#endif
+
+       return (u1*) s;
+}
+
+
+/************************ function: removenativestub ***************************
+
+    removes a previously created native-stub from memory
+    
+*******************************************************************************/
+
+void removenativestub (u1 *stub)
+{
+       CFREE (stub, NATIVESTUBSIZE * 8);
+}
+
diff --git a/alpha/native-math.h b/alpha/native-math.h
new file mode 100644 (file)
index 0000000..4e87509
--- /dev/null
@@ -0,0 +1,38 @@
+/************************* alpha/native-math.h *********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the machine-specific floating point definitions.
+
+       Authors: Michael Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+                Andreas Krall       EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/21
+
+*******************************************************************************/
+
+/* include machine-specific math.h */
+
+#include <math.h>
+
+/* define infinity for floating point numbers */
+
+u4 flt_nan    = 0xffffffff;
+u4 flt_posinf = 0x7f800000;
+u4 flt_neginf = 0xff800000;
+
+#define FLT_NAN    (*((float*) (&flt_nan)))
+#define FLT_POSINF (*((float*) (&flt_posinf)))
+#define FLT_NEGINF (*((float*) (&flt_neginf)))
+
+/* define infinity for double floating point numbers */
+
+u8 dbl_nan    = 0xffffffffffffffffL ;
+u8 dbl_posinf = 0x7ff0000000000000L ;
+u8 dbl_neginf = 0xfff0000000000000L ;
+
+#define DBL_NAN    (*((double*) (&dbl_nan)))
+#define DBL_POSINF (*((double*) (&dbl_posinf)))
+#define DBL_NEGINF (*((double*) (&dbl_neginf)))
diff --git a/alpha/ngen.c b/alpha/ngen.c
new file mode 100644 (file)
index 0000000..7fd8cd9
--- /dev/null
@@ -0,0 +1,2725 @@
+/***************************** alpha/ngen.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (ICMDs).
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/08/10
+
+*******************************************************************************/
+
+
+
+/*******************************************************************************
+
+Datatypes and Register Allocations:
+----------------------------------- 
+
+On 64-bit-machines (like the Alpha) all operands are stored in the
+registers in a 64-bit form, even when the correspondig JavaVM 
+operands only need 32 bits.
+This is done by a canonical representation:
+
+32-bit integers are allways stored as sign-extended 64-bit values
+(this approach is directly supported by the Alpha architecture and
+is very easy to implement).
+
+32-bit-floats are stored in a 64-bit doubleprecision register by
+simply expanding the exponent and mantissa with zeroes.
+(also supported by the architecture)
+
+
+Stackframes:
+
+The calling conventions and the layout of the stack is 
+explained in detail in the documention file: calling.doc
+
+*******************************************************************************/
+
+
+/*********** additional functions and macros to generate code *****************/
+
+#define BlockPtrOfPC(pc)        block+block_index[pc]
+
+#ifdef STATISTICS
+#define COUNT_SPILLS count_spills++
+#else
+#define COUNT_SPILLS
+#endif
+
+
+/* gen_nullptr_check(objreg) */
+
+#ifdef SOFTNULLPTRCHECK
+#define gen_nullptr_check(objreg) \
+       if (checknull) {\
+       M_BEQZ((objreg), 0);\
+       mcode_addxnullrefs(mcodeptr);\
+       }
+#else
+#define gen_nullptr_check(objreg)
+#endif
+
+
+/* MCODECHECK(icnt) */
+
+#define MCODECHECK(icnt) \
+       if((mcodeptr+(icnt))>mcodeend)mcodeptr=mcode_increase((u1*)mcodeptr)
+
+/* M_INTMOVE:
+     generates an integer-move from register a to b.
+     if a and b are the same int-register, no code will be generated.
+*/ 
+
+#define M_INTMOVE(a,b) if(a!=b){M_OR(a,a,b,0);}
+
+
+/* M_FLTMOVE:
+    generates a floating-point-move from register a to b.
+    if a and b are the same float-register, no code will be generated
+*/ 
+
+#define M_FLTMOVE(a,b) if(a!=b){M_FMOV(a,b);}
+
+
+/* var_to_reg_xxx:
+    this function generates code to fetch data from a pseudo-register
+    into a real register. 
+    If the pseudo-register has actually been assigned to a real 
+    register, no code will be emitted, since following operations
+    can use this register directly.
+    
+    v: pseudoregister to be fetched from
+    tempregnum: temporary register to be used if v is actually spilled to ram
+
+    return: the register number, where the operand can be found after 
+            fetching (this wil be either tempregnum or the register
+            number allready given to v)
+*/
+
+#define var_to_reg_int(regnr,v,tempnr) { \
+       if ((v)->flags & INMEMORY) \
+               {COUNT_SPILLS;M_LLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
+       else regnr=(v)->regoff; \
+}
+
+
+#define var_to_reg_flt(regnr,v,tempnr) { \
+       if ((v)->flags & INMEMORY) \
+               {COUNT_SPILLS;M_DLD(tempnr,REG_SP,8*(v)->regoff);regnr=tempnr;} \
+       else regnr=(v)->regoff; \
+}
+
+
+/* reg_of_var:
+     This function determines a register, to which the result of an
+     operation should go, when it is ultimatively intended to store the result
+     in pseudoregister v.
+     If v is assigned to an actual register, this register will be
+     returned.
+     Otherwise (when v is spilled) this function returns tempregnum.
+     If not already done, regoff and flags are set in the stack location.
+*/        
+
+static int reg_of_var(stackptr v, int tempregnum)
+{
+       varinfo      *var;
+
+       switch (v->varkind) {
+               case TEMPVAR:
+                       if (!(v->flags & INMEMORY))
+                               return(v->regoff);
+                       break;
+               case STACKVAR:
+                       var = &(interfaces[v->varnum][v->type]);
+                       v->regoff = var->regoff;
+                       if (!(var->flags & INMEMORY))
+                               return(var->regoff);
+                       break;
+               case LOCALVAR:
+                       var = &(locals[v->varnum][v->type]);
+                       v->regoff = var->regoff;
+                       if (!(var->flags & INMEMORY))
+                               return(var->regoff);
+                       break;
+               case ARGVAR:
+                       v->regoff = v->varnum;
+                       if (IS_FLT_DBL_TYPE(v->type)) {
+                               if (v->varnum < fltreg_argnum) {
+                                       v->regoff = argfltregs[v->varnum];
+                                       return(argfltregs[v->varnum]);
+                                       }
+                               }
+                       else
+                               if (v->varnum < intreg_argnum) {
+                                       v->regoff = argintregs[v->varnum];
+                                       return(argintregs[v->varnum]);
+                                       }
+                       v->regoff -= intreg_argnum;
+                       break;
+               }
+       v->flags |= INMEMORY;
+       return tempregnum;
+}
+
+
+/* store_reg_to_var_xxx:
+    This function generates the code to store the result of an operation
+    back into a spilled pseudo-variable.
+    If the pseudo-variable has not been spilled in the first place, this 
+    function will generate nothing.
+    
+    v ............ Pseudovariable
+    tempregnum ... Number of the temporary registers as returned by
+                   reg_of_var.
+*/     
+
+#define store_reg_to_var_int(sptr, tempregnum) {       \
+       if ((sptr)->flags & INMEMORY) {                    \
+               COUNT_SPILLS;                                  \
+               M_LST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
+               }                                              \
+       }
+
+#define store_reg_to_var_flt(sptr, tempregnum) {       \
+       if ((sptr)->flags & INMEMORY) {                    \
+               COUNT_SPILLS;                                  \
+               M_DST(tempregnum, REG_SP, 8 * (sptr)->regoff); \
+               }                                              \
+       }
+
+
+void asm_signal_exception(void *xptr, void *sigctx);
+
+void catch_NullPointerException(int sig, int code, void *sigctx)
+{
+       sigset_t nsig;
+
+       /* Reset signal handler - necessary for SysV, does no harm for BSD */
+
+       signal(sig, (void*) catch_NullPointerException);
+       sigemptyset(&nsig);
+       sigaddset(&nsig, sig);
+       sigprocmask(SIG_UNBLOCK, &nsig, 0);
+       asm_signal_exception(proto_java_lang_NullPointerException, sigctx);
+}
+
+#ifdef __osf__
+
+void init_exceptions(void)
+{
+
+#else
+
+#include <asm/fpu.h>
+
+extern unsigned long ieee_get_fp_control();
+extern void ieee_set_fp_control(unsigned long fp_control);
+
+void init_exceptions(void)
+{
+/* initialise floating point control */
+ieee_set_fp_control(ieee_get_fp_control()
+                    & ~IEEE_TRAP_ENABLE_INV
+                    & ~IEEE_TRAP_ENABLE_DZE
+/*                  & ~IEEE_TRAP_ENABLE_UNF   */
+                    & ~IEEE_TRAP_ENABLE_OVF);
+#endif
+
+       /* Catch signal we need to convert to exceptions */
+       if (!checknull) {
+#if defined(SIGSEGV)
+               signal(SIGSEGV, (void*) catch_NullPointerException);
+#endif
+#if defined(SIGBUS)
+               signal(SIGBUS, (void*) catch_NullPointerException);
+#endif
+               }
+}
+
+/*************************** function gen_mcode ********************************
+
+       generates machine code
+
+*******************************************************************************/
+
+#define        MethodPointer   -8
+#define        FrameSize       -12
+#define     IsSync          -16
+#define     IsLeaf          -20
+#define     IntSave         -24
+#define     FltSave         -28
+#define     ExTableSize     -32
+#define     ExTableStart    -32
+
+#define     ExEntrySize     -32
+#define     ExStartPC       -8
+#define     ExEndPC         -16
+#define     ExHandlerPC     -24
+#define     ExCatchType     -32
+
+static void gen_mcode()
+{
+       int  len, s1, s2, s3, d, bbs;
+       s4   a;
+       s4          *mcodeptr;
+       stackptr    src;
+       varinfo     *var;
+       basicblock  *bptr;
+       instruction *iptr;
+
+       {
+       int p, pa, t, l, r;
+
+       savedregs_num = (isleafmethod) ? 0 : 1;           /* space to save the RA */
+
+       /* space to save used callee saved registers */
+
+       savedregs_num += (savintregcnt - maxsavintreguse);
+       savedregs_num += (savfltregcnt - maxsavfltreguse);
+
+       parentargs_base = maxmemuse + savedregs_num;
+
+#ifdef USE_THREADS
+       if (checksync && (method->flags & ACC_SYNCHRONIZED))
+               parentargs_base++;
+#endif
+
+       /* create method header */
+
+       (void) dseg_addaddress(method);                         /* MethodPointer  */
+       (void) dseg_adds4(parentargs_base * 8);                 /* FrameSize      */
+
+#ifdef USE_THREADS
+       if (checksync && (method->flags & ACC_SYNCHRONIZED))
+               (void) dseg_adds4((maxmemuse + 1) * 8);             /* IsSync         */
+       else
+#endif
+               (void) dseg_adds4(0);                               /* IsSync         */
+                                              
+       (void) dseg_adds4(isleafmethod);                        /* IsLeaf         */
+       (void) dseg_adds4(savintregcnt - maxsavintreguse);      /* IntSave        */
+       (void) dseg_adds4(savfltregcnt - maxsavfltreguse);      /* FltSave        */
+       (void) dseg_adds4(exceptiontablelength);                /* ExTableSize    */
+
+       for (len = 0; len < exceptiontablelength; len++) {
+               dseg_addtarget(BlockPtrOfPC(extable[len].startpc));
+               dseg_addtarget(BlockPtrOfPC(extable[len].endpc));
+               dseg_addtarget(BlockPtrOfPC(extable[len].handlerpc));
+               (void) dseg_addaddress(extable[len].catchtype);
+               }
+
+       /* initialise mcode variables */
+       
+       mcodeptr = (s4*) mcodebase;
+       mcodeend = (s4*) (mcodebase + mcodesize);
+       MCODECHECK(128);
+
+       /* create stack frame (if necessary) */
+
+       if (parentargs_base)
+               {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
+
+       /* save return address and used callee saved registers */
+
+       p = parentargs_base;
+       if (!isleafmethod)
+               {p--;  M_LST (REG_RA, REG_SP, 8*p);}
+       for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
+               {p--; M_LST (savintregs[r], REG_SP, 8 * p);}
+       for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
+               {p--; M_DST (savfltregs[r], REG_SP, 8 * p);}
+
+       /* save monitorenter argument */
+
+#ifdef USE_THREADS
+       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+               if (method->flags & ACC_STATIC) {
+                       p = dseg_addaddress (class);
+                       M_LLD(REG_ITMP1, REG_PV, p);
+                       M_LST(REG_ITMP1, REG_SP, 8 * maxmemuse);
+                       } 
+               else {
+                       M_LST (argintregs[0], REG_SP, 8 * maxmemuse);
+                       }
+               }                       
+#endif
+
+       if (runverbose && isleafmethod) {
+               M_LDA (REG_SP, REG_SP, -(8*8));
+               M_LST(REG_RA, REG_SP, 1*8);
+               M_LST(argintregs[0], REG_SP, 2*8);
+               M_LST(argintregs[1], REG_SP, 3*8);
+               M_LST(argintregs[2], REG_SP, 4*8);
+               M_LST(argintregs[3], REG_SP, 5*8);
+               M_LST(argintregs[4], REG_SP, 6*8);
+               M_LST(argintregs[5], REG_SP, 7*8);
+               p = dseg_addaddress (method);
+               M_LLD(REG_ITMP1, REG_PV, p);
+               M_LST(REG_ITMP1, REG_SP, 0);
+               p = dseg_addaddress ((void*) (builtin_trace_args));
+               M_LLD(REG_PV, REG_PV, p);
+               M_JSR(REG_RA, REG_PV);
+               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+               M_LLD(REG_RA, REG_SP, 1*8);
+               M_LLD(argintregs[0], REG_SP, 2*8);
+               M_LLD(argintregs[1], REG_SP, 3*8);
+               M_LLD(argintregs[2], REG_SP, 4*8);
+               M_LLD(argintregs[3], REG_SP, 5*8);
+               M_LLD(argintregs[4], REG_SP, 6*8);
+               M_LLD(argintregs[5], REG_SP, 7*8);
+               M_LDA (REG_SP, REG_SP, 8*8);
+               }
+
+       /* take arguments out of register or stack frame */
+
+       for (p = 0, l = 0; p < mparamcount; p++) {
+               t = mparamtypes[p];
+               var = &(locals[l][t]);
+               l++;
+               if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
+                       l++;
+               if (var->type < 0)
+                       continue;
+               r = var->regoff; 
+               if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
+                       if (p < INT_ARG_CNT) {                   /* register arguments    */
+                               if (!(var->flags & INMEMORY))        /* reg arg -> register   */
+                                       {M_INTMOVE (argintregs[p], r);}
+                               else                                 /* reg arg -> spilled    */
+                                       M_LST (argintregs[p], REG_SP, 8 * r);
+                               }
+                       else {                                   /* stack arguments       */
+                               pa = p - INT_ARG_CNT;
+                               if (!(var->flags & INMEMORY))        /* stack arg -> register */ 
+                                       M_LLD (r, REG_SP, 8 * (parentargs_base + pa));
+                               else {                               /* stack arg -> spilled  */
+                                       M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
+                                       M_LST (REG_ITMP1, REG_SP, 8 * r);
+                                       }
+                               }
+                       }
+               else {                                       /* floating args         */   
+                       if (p < FLT_ARG_CNT) {                   /* register arguments    */
+                               if (!(var->flags & INMEMORY))        /* reg arg -> register   */
+                                       {M_FLTMOVE (argfltregs[p], r);}
+                               else                                             /* reg arg -> spilled    */
+                                       M_DST (argfltregs[p], REG_SP, 8 * r);
+                               }
+                       else {                                   /* stack arguments       */
+                               pa = p - FLT_ARG_CNT;
+                               if (!(var->flags & INMEMORY))        /* stack-arg -> register */
+                                       M_DLD (r, REG_SP, 8 * (parentargs_base + pa) );
+                               else {                               /* stack-arg -> spilled  */
+                                       M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
+                                       M_DST (REG_FTMP1, REG_SP, 8 * r);
+                                       }
+                               }
+                       }
+               }  /* end for */
+
+       if (runverbose && !isleafmethod) {
+               M_LDA (REG_SP, REG_SP, -8);
+               p = dseg_addaddress (method);
+               M_LLD(REG_ITMP1, REG_PV, p);
+               M_LST(REG_ITMP1, REG_SP, 0);
+               p = dseg_addaddress ((void*) (builtin_trace_args));
+               M_LLD(REG_PV, REG_PV, p);
+               M_JSR(REG_RA, REG_PV);
+               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+               M_LDA(REG_SP, REG_SP, 8);
+               }
+
+#ifdef USE_THREADS
+       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+               p = dseg_addaddress ((void*) (builtin_monitorenter));
+               M_LLD(REG_PV, REG_PV, p);
+               M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+               M_JSR(REG_RA, REG_PV);
+               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+               }                       
+#endif
+       }
+
+       /* end of header generation */
+
+       for (bbs = block_count, bptr = block; --bbs >= 0; bptr++) {
+               bptr -> mpc = (int)((u1*) mcodeptr - mcodebase);
+
+               /* branch resolving */
+
+               {
+               branchref *brefs;
+               for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
+                       gen_resolvebranch((u1*) mcodebase + brefs->branchpos, 
+                                         brefs->branchpos, bptr->mpc);
+                       }
+               }
+               src = bptr->instack;
+               len = bptr->indepth;
+               MCODECHECK(64+len);
+               while (src != NULL) {
+                       len--;
+                       if ((len == 0) && (bptr->type != BBTYPE_STD)) {
+                               d = reg_of_var(src, REG_ITMP1);
+                               M_INTMOVE(REG_ITMP1, d);
+                               store_reg_to_var_int(src, d);
+                               }
+                       else {
+                               d = reg_of_var(src, REG_IFTMP);
+                               if ((src->varkind != STACKVAR)) {
+                                       s2 = src->type;
+                                       if (IS_FLT_DBL_TYPE(s2)) {
+                                               if (!(interfaces[len][s2].flags & INMEMORY)) {
+                                                       s1 = interfaces[len][s2].regoff;
+                                                       M_FLTMOVE(s1,d);
+                                                       }
+                                               else {
+                                                       M_DLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
+                                                       }
+                                               store_reg_to_var_flt(src, d);
+                                               }
+                                       else {
+                                               if (!(interfaces[len][s2].flags & INMEMORY)) {
+                                                       s1 = interfaces[len][s2].regoff;
+                                                       M_INTMOVE(s1,d);
+                                                       }
+                                               else {
+                                                       M_LLD(d, REG_SP, 8 * interfaces[len][s2].regoff);
+                                                       }
+                                               store_reg_to_var_int(src, d);
+                                               }
+                                       }
+                               }
+                       src = src->prev;
+                       }
+               s1  = bptr[0].ipc;
+               src = bptr->instack;
+               len = bptr[1].ipc - s1;
+               for (iptr = &instr[s1];
+                   len > 0;
+                   src = iptr->dst, len--, iptr++) {
+
+       MCODECHECK(64);
+       switch (iptr->opc) {
+
+               case ICMD_NOP:
+                       break;
+
+               case ICMD_NULLCHECKPOP:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       gen_nullptr_check(s1);
+                       break;
+
+               /*********************** constant operations **************************/
+
+               case ICMD_ICONST:
+                       d = reg_of_var(iptr->dst, REG_ITMP1);
+                       if ( (iptr->val.i >= -32768) && (iptr->val.i <= 32767) ) {
+                               M_LDA(d, REG_ZERO, iptr->val.i);
+                               } 
+                       else {
+                               a = dseg_adds4 (iptr->val.i);
+                               M_ILD(d, REG_PV, a);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_LCONST:
+                       d = reg_of_var(iptr->dst, REG_ITMP1);
+                       if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767) ) {
+                               M_LDA(d, REG_ZERO, iptr->val.l);
+                               } 
+                       else {
+                               a = dseg_adds8 (iptr->val.l);
+                               M_LLD(d, REG_PV, a);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_FCONST:
+                       d = reg_of_var (iptr->dst, REG_FTMP1);
+                       a = dseg_addfloat (iptr->val.f);
+                       M_FLD(d, REG_PV, a);
+                       store_reg_to_var_flt (iptr->dst, d);
+                       break;
+                       
+               case ICMD_DCONST:
+                       d = reg_of_var (iptr->dst, REG_FTMP1);
+                       a = dseg_adddouble (iptr->val.d);
+                       M_DLD(d, REG_PV, a);
+                       store_reg_to_var_flt (iptr->dst, d);
+                       break;
+
+
+               case ICMD_ACONST:
+                       d = reg_of_var(iptr->dst, REG_ITMP1);
+                       if (iptr->val.a) {
+                               a = dseg_addaddress (iptr->val.a);
+                               M_LLD(d, REG_PV, a);
+                               }
+                       else {
+                               M_INTMOVE(REG_ZERO, d);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               /********************** load/store operations *************************/
+
+               case ICMD_ILOAD:
+               case ICMD_LLOAD:
+               case ICMD_ALOAD:
+                       d = reg_of_var(iptr->dst, REG_ITMP1);
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                           (iptr->dst->varnum == iptr->op1))
+                               break;
+                       var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       if (var->flags & INMEMORY)
+                               M_LLD(d, REG_SP, 8 * var->regoff);
+                       else
+                               {M_INTMOVE(var->regoff,d);}
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_FLOAD:
+               case ICMD_DLOAD:
+                       d = reg_of_var(iptr->dst, REG_FTMP1);
+                       if ((iptr->dst->varkind == LOCALVAR) &&
+                           (iptr->dst->varnum == iptr->op1))
+                               break;
+                       var = &(locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
+                       if (var->flags & INMEMORY)
+                               M_DLD(d, REG_SP, 8 * var->regoff);
+                       else
+                               {M_FLTMOVE(var->regoff,d);}
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+
+               case ICMD_ISTORE:
+               case ICMD_LSTORE:
+               case ICMD_ASTORE:
+                       if ((src->varkind == LOCALVAR) &&
+                           (src->varnum == iptr->op1))
+                               break;
+                       var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               var_to_reg_int(s1, src, REG_ITMP1);
+                               M_LST(s1, REG_SP, 8 * var->regoff);
+                               }
+                       else {
+                               var_to_reg_int(s1, src, var->regoff);
+                               M_INTMOVE(s1, var->regoff);
+                               }
+                       break;
+
+               case ICMD_FSTORE:
+               case ICMD_DSTORE:
+                       if ((src->varkind == LOCALVAR) &&
+                           (src->varnum == iptr->op1))
+                               break;
+                       var = &(locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
+                       if (var->flags & INMEMORY) {
+                               var_to_reg_flt(s1, src, REG_FTMP1);
+                               M_DST(s1, REG_SP, 8 * var->regoff);
+                               }
+                       else {
+                               var_to_reg_flt(s1, src, var->regoff);
+                               M_FLTMOVE(s1, var->regoff);
+                               }
+                       break;
+
+
+               /******************* pop/dup/swap operations **************************/
+
+               case ICMD_POP:
+               case ICMD_POP2:
+                       break;
+
+#define M_COPY(from,to) \
+                       d = reg_of_var(to, REG_IFTMP); \
+                       if ((from->regoff != to->regoff) || \
+                           ((from->flags ^ to->flags) & INMEMORY)) { \
+                               if (IS_FLT_DBL_TYPE(from->type)) { \
+                                       var_to_reg_flt(s1, from, d); \
+                                       M_FLTMOVE(s1,d); \
+                                       store_reg_to_var_flt(to, d); \
+                                       }\
+                               else { \
+                                       var_to_reg_int(s1, from, d); \
+                                       M_INTMOVE(s1,d); \
+                                       store_reg_to_var_int(to, d); \
+                                       }\
+                               }
+
+               case ICMD_DUP:
+                       M_COPY(src, iptr->dst);
+                       break;
+
+               case ICMD_DUP_X1:
+                       M_COPY(src,       iptr->dst->prev->prev);
+               case ICMD_DUP2:
+                       M_COPY(src,       iptr->dst);
+                       M_COPY(src->prev, iptr->dst->prev);
+                       break;
+
+               case ICMD_DUP2_X1:
+                       M_COPY(src->prev,       iptr->dst->prev->prev->prev);
+               case ICMD_DUP_X2:
+                       M_COPY(src,             iptr->dst);
+                       M_COPY(src->prev,       iptr->dst->prev);
+                       M_COPY(src->prev->prev, iptr->dst->prev->prev);
+                       M_COPY(src, iptr->dst->prev->prev->prev);
+                       break;
+
+               case ICMD_DUP2_X2:
+                       M_COPY(src,                   iptr->dst);
+                       M_COPY(src->prev,             iptr->dst->prev);
+                       M_COPY(src->prev->prev,       iptr->dst->prev->prev);
+                       M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
+                       M_COPY(src,       iptr->dst->prev->prev->prev->prev);
+                       M_COPY(src->prev, iptr->dst->prev->prev->prev->prev->prev);
+                       break;
+
+               case ICMD_SWAP:
+                       M_COPY(src, iptr->dst->prev);
+                       M_COPY(src->prev, iptr->dst);
+                       break;
+
+
+               /********************* integer operations *****************************/
+
+               case ICMD_INEG:
+                       var_to_reg_int(s1, src, REG_ITMP1); 
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_ISUB(REG_ZERO, s1, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_LNEG:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_LSUB(REG_ZERO, s1, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_I2L:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_INTMOVE(s1, d);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_L2I:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_IADD(s1, REG_ZERO, d , 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_INT2BYTE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_BSEXT(s1, d);
+                               }
+                       else {
+                               M_SLL(s1,56, d, 1);
+                               M_SRA( d,56, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_INT2CHAR:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+            M_ZAPNOT(s1, 0x03, d, 1);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_INT2SHORT:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_SSEXT(s1, d);
+                               }
+                       else {
+                               M_SLL( s1, 48, d, 1);
+                               M_SRA(  d, 48, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+#define ICONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
+                    else{a=dseg_adds4(c);M_ILD(r,REG_PV,a);}
+
+#define LCONST(r,c) if(((c)>=-32768)&&((c)<= 32767)){M_LDA(r,REG_ZERO,c);} \
+                    else{a=dseg_adds8(c);M_LLD(r,REG_PV,a);}
+
+
+               case ICMD_IADD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_IADD(s1, s2, d,  0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IADDCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_IADD(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_IADD(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LADD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_LADD(s1, s2, d,  0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LADDCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_LADD(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_LADD(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_ISUB:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_ISUB(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_ISUBCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_ISUB(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_ISUB(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LSUB:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_LSUB(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LSUBCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_LSUB(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_LSUB(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_IMUL:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_IMUL(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IMULCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_IMUL(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_IMUL(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LMUL:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_LMUL (s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LMULCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_LMUL(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_LMUL(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+                   
+               case ICMD_ISHL:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_AND(s2, 0x1f, REG_ITMP3, 1);
+                       M_SLL(s1, REG_ITMP3, d, 0);
+                       M_IADD(d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_ISHLCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SLL(s1, iptr->val.i & 0x1f, d, 1);
+                       M_IADD(d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_ISHR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_AND(s2, 0x1f, REG_ITMP3,  1);
+                       M_SRA(s1, REG_ITMP3, d,   0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_ISHRCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SRA(s1, iptr->val.i & 0x1f, d, 1);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_IUSHR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_AND   (s2, 0x1f, REG_ITMP2,  1);
+            M_ZAPNOT(s1, 0x0f, d, 1);
+                       M_SRL   ( d, REG_ITMP2, d, 0);
+                       M_IADD  ( d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IUSHRCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+            M_ZAPNOT(s1, 0x0f, d, 1);
+                       M_SRL(d, iptr->val.i & 0x1f, d, 1);
+                       M_IADD(d, REG_ZERO, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_LSHL:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SLL(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LSHLCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SLL(s1, iptr->val.l & 0x3f, d, 1);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_LSHR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SRA(s1, s2, d,  0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LSHRCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SRA(s1, iptr->val.l & 0x3f, d, 1);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_LUSHR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SRL(s1, s2, d,  0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LUSHRCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_SRL(s1, iptr->val.l & 0x3f, d, 1);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_IAND:
+               case ICMD_LAND:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_AND(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IANDCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_AND(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_AND(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LANDCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_AND(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_AND(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_IOR:
+               case ICMD_LOR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_OR( s1,s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IORCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_OR(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_OR(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LORCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_OR(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_OR(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_IXOR:
+               case ICMD_LXOR:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_XOR(s1, s2, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IXORCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_XOR(s1, iptr->val.i, d, 1);
+                               }
+                       else {
+                               ICONST(REG_ITMP2, iptr->val.i);
+                               M_XOR(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LXORCONST:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
+                               M_XOR(s1, iptr->val.l, d, 1);
+                               }
+                       else {
+                               LCONST(REG_ITMP2, iptr->val.l);
+                               M_XOR(s1, REG_ITMP2, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+
+               case ICMD_LCMP:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       M_CMPLT(s1, s2, REG_ITMP3, 0);
+                       M_CMPLT(s2, s1, REG_ITMP1, 0);
+                       M_LSUB (REG_ITMP1, REG_ITMP3, d, 0);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+
+               case ICMD_IINC:
+                       var = &(locals[iptr->op1][TYPE_INT]);
+                       if (var->flags & INMEMORY) {
+                               s1 = REG_ITMP1;
+                               M_LLD(s1, REG_SP, 8 * var->regoff);
+                               }
+                       else
+                               s1 = var->regoff;
+                       if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
+                               M_IADD(s1, iptr->val.i, s1, 1);
+                               }
+                       else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
+                               M_ISUB(s1, (-iptr->val.i), s1, 1);
+                               }
+                       else {
+                               M_LDA (s1, s1, iptr->val.i);
+                               M_IADD(s1, REG_ZERO, s1, 0);
+                               }
+                       if (var->flags & INMEMORY)
+                               M_LST(s1, REG_SP, 8 * var->regoff);
+                       break;
+
+
+               /*********************** floating operations **************************/
+
+               case ICMD_FNEG:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       M_FMOVN(s1, d);
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DNEG:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       M_FMOVN(s1, d);
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+               case ICMD_FADD:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_FADDS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_FADD(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DADD:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_DADDS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_DADD(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+               case ICMD_FSUB:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_FSUBS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_FSUB(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DSUB:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_DSUBS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_DSUB(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+               case ICMD_FMUL:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_FMULS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_FMUL(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DMUL:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_DMULS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_DMUL(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+               case ICMD_FDIV:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_FDIVS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_FDIV(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DDIV:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_DDIVS(s1, s2, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_DDIV(s1, s2, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               
+               case ICMD_FREM:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_FDIVS(s1,s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_CVTDL_CS(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+                               M_TRAPB;
+                               M_CVTLF(REG_ZERO, REG_FTMP3, REG_FTMP3);
+                               M_FMULS(REG_FTMP3, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FSUBS(s1, REG_FTMP3, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_FDIV(s1,s2, REG_FTMP3);
+                               M_CVTDL_C(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+                               M_CVTLF(REG_ZERO, REG_FTMP3, REG_FTMP3);
+                               M_FMUL(REG_FTMP3, s2, REG_FTMP3);
+                               M_FSUB(s1, REG_FTMP3, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                   break;
+               case ICMD_DREM:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_DDIVS(s1,s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_CVTDL_CS(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+                               M_TRAPB;
+                               M_CVTLD(REG_ZERO, REG_FTMP3, REG_FTMP3);
+                               M_DMULS(REG_FTMP3, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_DSUBS(s1, REG_FTMP3, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_DDIV(s1,s2, REG_FTMP3);
+                               M_CVTDL_C(REG_ZERO, REG_FTMP3, REG_FTMP3); /* round to integer */
+                               M_CVTLD(REG_ZERO, REG_FTMP3, REG_FTMP3);
+                               M_DMUL(REG_FTMP3, s2, REG_FTMP3);
+                               M_DSUB(s1, REG_FTMP3, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                   break;
+
+               case ICMD_I2F:
+               case ICMD_L2F:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       a = dseg_adddouble(0.0);
+                       M_LST (s1, REG_PV, a);
+                       M_DLD (d, REG_PV, a);
+                       M_CVTLF(REG_ZERO, d, d);
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+
+               case ICMD_I2D:
+               case ICMD_L2D:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       a = dseg_adddouble(0.0);
+                       M_LST (s1, REG_PV, a);
+                       M_DLD (d, REG_PV, a);
+                       M_CVTLD(REG_ZERO, d, d);
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+                       
+               case ICMD_F2I:
+               case ICMD_D2I:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       a = dseg_adddouble(0.0);
+                       if (checkfloats) {
+                               M_CVTDL_CS(REG_ZERO, s1, REG_FTMP1);
+                               M_TRAPB;
+                               M_CVTLIS(REG_FTMP1, REG_FTMP2);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_CVTDL_C(REG_ZERO, s1, REG_FTMP1);
+                               M_CVTLI(REG_FTMP1, REG_FTMP2);
+                               }
+                       M_DST (REG_FTMP1, REG_PV, a);
+                       M_ILD (d, REG_PV, a);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               
+               case ICMD_F2L:
+               case ICMD_D2L:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       a = dseg_adddouble(0.0);
+                       if (checkfloats) {
+                               M_CVTDL_CS(REG_ZERO, s1, REG_FTMP1);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_CVTDL_C(REG_ZERO, s1, REG_FTMP1);
+                               }
+                       M_DST (REG_FTMP1, REG_PV, a);
+                       M_LLD (d, REG_PV, a);
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_F2D:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       M_FLTMOVE(s1, d);
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+                                       
+               case ICMD_D2F:
+                       var_to_reg_flt(s1, src, REG_FTMP1);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       if (checkfloats) {
+                               M_CVTDFS(REG_ZERO, s1, d);
+                               M_TRAPB;
+                               }
+                       else {
+                               M_CVTDF(REG_ZERO, s1, d);
+                               }
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               
+               case ICMD_FCMPL:
+               case ICMD_DCMPL:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if (checkfloats) {
+                               M_LSUB  (REG_ZERO, 1, d, 1);
+                               M_FCMPEQS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instructions         */
+                               M_OR    (REG_ZERO, REG_ZERO, d, 0);
+                               M_FCMPLTS(s2, s1, REG_FTMP3);
+                               M_TRAPB;
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_LADD  (REG_ZERO, 1, d, 1);
+                               }
+                       else {
+                               M_LSUB  (REG_ZERO, 1, d, 1);
+                               M_FCMPEQ(s1, s2, REG_FTMP3);
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instructions         */
+                               M_OR    (REG_ZERO, REG_ZERO, d, 0);
+                               M_FCMPLT(s2, s1, REG_FTMP3);
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_LADD  (REG_ZERO, 1, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+                       
+               case ICMD_FCMPG:
+               case ICMD_DCMPG:
+                       var_to_reg_flt(s1, src->prev, REG_FTMP1);
+                       var_to_reg_flt(s2, src, REG_FTMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       if (checkfloats) {
+                               M_LADD  (REG_ZERO, 1, d, 1);
+                               M_FCMPEQS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_OR    (REG_ZERO, REG_ZERO, d, 0);
+                               M_FCMPLTS(s1, s2, REG_FTMP3);
+                               M_TRAPB;
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_LSUB  (REG_ZERO, 1, d, 1);
+                               }
+                       else {
+                               M_LADD  (REG_ZERO, 1, d, 1);
+                               M_FCMPEQ(s1, s2, REG_FTMP3);
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_OR    (REG_ZERO, REG_ZERO, d, 0);
+                               M_FCMPLT(s1, s2, REG_FTMP3);
+                               M_FBEQZ (REG_FTMP3, 1);    /* jump over next instruction          */
+                               M_LSUB  (REG_ZERO, 1, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+
+               /********************** memory operations *****************************/
+
+#define gen_bound_check \
+                       if (checkbounds) {\
+                       M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));\
+                       M_CMPULT(s2, REG_ITMP3, REG_ITMP3, 0);\
+                       M_BEQZ(REG_ITMP3, 0);\
+                       mcode_addxboundrefs(mcodeptr);\
+                       }
+
+               case ICMD_ARRAYLENGTH:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       M_ILD(d, s1, OFFSET(java_arrayheader, size));
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_AALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_LLD( d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_LALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_IALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_FALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_DALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_FTMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       store_reg_to_var_flt(iptr->dst, d);
+                       break;
+               case ICMD_CALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       if (has_ext_instr_set) {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               }
+                       else {
+                               M_LADD (s2, s1, REG_ITMP1,  0);
+                               M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_LDA  (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_EXTWL(REG_ITMP2, REG_ITMP1, d, 0);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;                  
+               case ICMD_SALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       if (has_ext_instr_set) {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+                               M_SSEXT(d, d);
+                               }
+                       else {
+                               M_LADD(s2, s1, REG_ITMP1,  0);
+                               M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
+                               M_EXTQH(REG_ITMP2, REG_ITMP1, d, 0);
+                               M_SRA(d, 48, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+               case ICMD_BALOAD:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       if (has_ext_instr_set) {
+                               M_LADD   (s2, s1, REG_ITMP1, 0);
+                               M_BLDU   (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
+                               M_BSEXT  (d, d);
+                               }
+                       else {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                               M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
+                               M_EXTQH(REG_ITMP2, REG_ITMP1, d, 0);
+                               M_SRA(d, 56, d, 1);
+                               }
+                       store_reg_to_var_int(iptr->dst, d);
+                       break;
+
+               case ICMD_AASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_LST   (s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
+                       break;
+               case ICMD_LASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_LST   (s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
+                       break;
+               case ICMD_IASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_IST   (s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
+                       break;
+               case ICMD_FASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_flt(s3, src, REG_FTMP3);
+                       M_S4ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_FST   (s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
+                       break;
+               case ICMD_DASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_flt(s3, src, REG_FTMP3);
+                       M_S8ADDQ(s2, s1, REG_ITMP1, 0);
+                       M_DST   (s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
+                       break;
+               case ICMD_CASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SST (s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               }
+                       else {
+                               M_LADD (s2, s1, REG_ITMP1, 0);
+                               M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_LDA  (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
+                               M_INSWL(s3, REG_ITMP1, REG_ITMP3, 0);
+                               M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+                               M_OR   (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+                               M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+               case ICMD_SASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_LADD(s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_SST (s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               }
+                       else {
+                               M_LADD (s2, s1, REG_ITMP1, 0);
+                               M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_LDA  (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
+                               M_INSWL(s3, REG_ITMP1, REG_ITMP3, 0);
+                               M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+                               M_OR   (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+                               M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+               case ICMD_BASTORE:
+                       var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src->prev, REG_ITMP2);
+                       gen_nullptr_check(s1);
+                       gen_bound_check;
+                       var_to_reg_int(s3, src, REG_ITMP3);
+                       if (has_ext_instr_set) {
+                               M_LADD(s2, s1, REG_ITMP1, 0);
+                               M_BST (s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                               }
+                       else {
+                               M_LADD (s2, s1, REG_ITMP1,  0);
+                               M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                               M_LDA  (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
+                               M_INSBL(s3, REG_ITMP1, REG_ITMP3, 0);
+                               M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
+                               M_OR   (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
+                               M_LST_U(REG_ITMP2, REG_ITMP1, 0);
+                               }
+                       break;
+
+
+               case ICMD_PUTSTATIC:
+                       a = dseg_addaddress (iptr->val.a);
+                       M_LLD(REG_ITMP1, REG_PV, a);
+                       switch (iptr->op1) {
+                               case TYPE_INT:
+                                       var_to_reg_int(s2, src, REG_ITMP2);
+                                       M_IST(s2, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_LNG:
+                               case TYPE_ADR:
+                                       var_to_reg_int(s2, src, REG_ITMP2);
+                                       M_LST(s2, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_FLT:
+                                       var_to_reg_flt(s2, src, REG_FTMP2);
+                                       M_FST(s2, REG_ITMP1, 0);
+                                       break;
+                               case TYPE_DBL:
+                                       var_to_reg_flt(s2, src, REG_FTMP2);
+                                       M_DST(s2, REG_ITMP1, 0);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+               case ICMD_GETSTATIC:
+                       a = dseg_addaddress (iptr->val.a);
+                       M_LLD(REG_ITMP1, REG_PV, a);
+                       switch (iptr->op1) {
+                               case TYPE_INT:
+                                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                                       M_ILD(d, REG_ITMP1, 0);
+                                       store_reg_to_var_int(iptr->dst, d);
+                                       break;
+                               case TYPE_LNG:
+                               case TYPE_ADR:
+                                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                                       M_LLD(d, REG_ITMP1, 0);
+                                       store_reg_to_var_int(iptr->dst, d);
+                                       break;
+                               case TYPE_FLT:
+                                       d = reg_of_var(iptr->dst, REG_FTMP1);
+                                       M_FLD(d, REG_ITMP1, 0);
+                                       store_reg_to_var_flt(iptr->dst, d);
+                                       break;
+                               case TYPE_DBL:                          
+                                       d = reg_of_var(iptr->dst, REG_FTMP1);
+                                       M_DLD(d, REG_ITMP1, 0);
+                                       store_reg_to_var_flt(iptr->dst, d);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+
+               case ICMD_PUTFIELD:
+                       switch (iptr->op1) {
+                               case TYPE_INT:
+                                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                                       var_to_reg_int(s2, src, REG_ITMP2);
+                                       gen_nullptr_check(s1);
+                                       M_IST(s2, s1, iptr->val.i);
+                                       break;
+                               case TYPE_LNG:
+                               case TYPE_ADR:
+                                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                                       var_to_reg_int(s2, src, REG_ITMP2);
+                                       gen_nullptr_check(s1);
+                                       M_LST(s2, s1, iptr->val.i);
+                                       break;
+                               case TYPE_FLT:
+                                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                                       var_to_reg_flt(s2, src, REG_FTMP2);
+                                       gen_nullptr_check(s1);
+                                       M_FST(s2, s1, iptr->val.i);
+                                       break;
+                               case TYPE_DBL:
+                                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                                       var_to_reg_flt(s2, src, REG_FTMP2);
+                                       gen_nullptr_check(s1);
+                                       M_DST(s2, s1, iptr->val.i);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+               case ICMD_GETFIELD:
+                       switch (iptr->op1) {
+                               case TYPE_INT:
+                                       var_to_reg_int(s1, src, REG_ITMP1);
+                                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                                       gen_nullptr_check(s1);
+                                       M_ILD(d, s1, iptr->val.i);
+                                       store_reg_to_var_int(iptr->dst, d);
+                                       break;
+                               case TYPE_LNG:
+                               case TYPE_ADR:
+                                       var_to_reg_int(s1, src, REG_ITMP1);
+                                       d = reg_of_var(iptr->dst, REG_ITMP3);
+                                       gen_nullptr_check(s1);
+                                       M_LLD(d, s1, iptr->val.i);
+                                       store_reg_to_var_int(iptr->dst, d);
+                                       break;
+                               case TYPE_FLT:
+                                       var_to_reg_int(s1, src, REG_ITMP1);
+                                       d = reg_of_var(iptr->dst, REG_FTMP1);
+                                       gen_nullptr_check(s1);
+                                       M_FLD(d, s1, iptr->val.i);
+                                       store_reg_to_var_flt(iptr->dst, d);
+                                       break;
+                               case TYPE_DBL:                          
+                                       var_to_reg_int(s1, src, REG_ITMP1);
+                                       d = reg_of_var(iptr->dst, REG_FTMP1);
+                                       gen_nullptr_check(s1);
+                                       M_DLD(d, s1, iptr->val.i);
+                                       store_reg_to_var_flt(iptr->dst, d);
+                                       break;
+                               default: panic ("internal error");
+                               }
+                       break;
+
+
+               /********************** branch operations *****************************/
+
+#define ALIGNCODENOP {if((int)((long)mcodeptr&7)){M_NOP;}}
+
+               case ICMD_ATHROW:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       M_INTMOVE(s1, REG_ITMP1_XPTR);
+                       a = dseg_addaddress(asm_handle_exception);
+                       M_LLD(REG_ITMP2, REG_PV, a);
+                       M_JMP(REG_ITMP2_XPC, REG_ITMP2);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_GOTO:
+                       M_BR(0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_JSR:
+                       M_BSR(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+                       
+               case ICMD_RET:
+                       var = &(locals[iptr->op1][TYPE_ADR]);
+                       if (var->flags & INMEMORY) {
+                               M_LLD(REG_ITMP1, REG_SP, 8 * var->regoff);
+                               M_RET(REG_ZERO, REG_ITMP1);
+                               }
+                       else
+                               M_RET(REG_ZERO, var->regoff);
+                       ALIGNCODENOP;
+                       break;
+
+               case ICMD_IFNULL:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       M_BEQZ(s1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFNONNULL:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       M_BNEZ(s1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+
+               case ICMD_IFEQ:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BEQZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPEQ(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFLT:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BLTZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPLT(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFLE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BLEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPLE(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFNE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BNEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPEQ(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFGT:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BGTZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPLE(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IFGE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.i == 0) {
+                               M_BGEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
+                                       M_CMPLT(s1, iptr->val.i, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       ICONST(REG_ITMP2, iptr->val.i);
+                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+
+               case ICMD_IF_LEQ:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BEQZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPEQ(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_LLT:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BLTZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPLT(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_LLE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BLEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPLE(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BNEZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_LNE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BNEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPEQ(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_LGT:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BGTZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPLE(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPLE(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_LGE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (iptr->val.l == 0) {
+                               M_BGEZ(s1, 0);
+                               }
+                       else {
+                               if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
+                                       M_CMPLT(s1, iptr->val.l, REG_ITMP1, 1);
+                                       }
+                               else {
+                                       LCONST(REG_ITMP2, iptr->val.l);
+                                       M_CMPLT(s1, REG_ITMP2, REG_ITMP1, 0);
+                                       }
+                               M_BEQZ(REG_ITMP1, 0);
+                               }
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+
+               case ICMD_IF_ICMPEQ:
+               case ICMD_IF_LCMPEQ:
+               case ICMD_IF_ACMPEQ:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPEQ(s1, s2, REG_ITMP1, 0);
+                       M_BNEZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_LCMPNE:
+               case ICMD_IF_ACMPNE:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPEQ(s1, s2, REG_ITMP1, 0);
+                       M_BEQZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_LCMPLT:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPLT(s1, s2, REG_ITMP1, 0);
+                       M_BNEZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_LCMPGT:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPLE(s1, s2, REG_ITMP1, 0);
+                       M_BEQZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_ICMPLE:
+               case ICMD_IF_LCMPLE:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPLE(s1, s2, REG_ITMP1, 0);
+                       M_BNEZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+               case ICMD_IF_ICMPGE:
+               case ICMD_IF_LCMPGE:
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPLT(s1, s2, REG_ITMP1,  0);
+                       M_BEQZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+                       break;
+
+/*   branch if the unsigned value of s1 is greater that s2 (note, that s2 has
+        to be >= 0) */
+
+/*             case ICMD_IF_UCMPGE: 
+                       var_to_reg_int(s1, src->prev, REG_ITMP1);
+                       var_to_reg_int(s2, src, REG_ITMP2);
+                       M_CMPULE(s2, s1, REG_ITMP1, 0);
+                       M_BNEZ(REG_ITMP1, 0);
+                       mcode_addreference(BlockPtrOfPC(iptr->op1), mcodeptr);
+            break;
+*/
+
+               case ICMD_IRETURN:
+               case ICMD_LRETURN:
+               case ICMD_ARETURN:
+
+#ifdef USE_THREADS
+                       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+                               a = dseg_addaddress ((void*) (builtin_monitorexit));
+                               M_LLD(REG_PV, REG_PV, a);
+                               M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+                               M_JSR(REG_RA, REG_PV);
+                               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+                               }                       
+#endif
+                       var_to_reg_int(s1, src, REG_RESULT);
+                       M_INTMOVE(s1, REG_RESULT);
+                       goto nowperformreturn;
+
+               case ICMD_FRETURN:
+               case ICMD_DRETURN:
+
+#ifdef USE_THREADS
+                       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+                               a = dseg_addaddress ((void*) (builtin_monitorexit));
+                               M_LLD(REG_PV, REG_PV, a);
+                               M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+                               M_JSR(REG_RA, REG_PV);
+                               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+                               }                       
+#endif
+                       var_to_reg_flt(s1, src, REG_FRESULT);
+                       M_FLTMOVE(s1, REG_FRESULT);
+                       goto nowperformreturn;
+
+               case ICMD_RETURN:
+
+#ifdef USE_THREADS
+                       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+                               a = dseg_addaddress ((void*) (builtin_monitorexit));
+                               M_LLD(REG_PV, REG_PV, a);
+                               M_LLD(argintregs[0], REG_SP, 8 * maxmemuse);
+                               M_JSR(REG_RA, REG_PV);
+                               M_LDA(REG_PV, REG_RA, -(int)((u1*) mcodeptr - mcodebase));
+                               }                       
+#endif
+
+nowperformreturn:
+                       {
+                       int r, p;
+                       
+                       p = parentargs_base;
+                       if (!isleafmethod)
+                               {p--;  M_LLD (REG_RA, REG_SP, 8 * p);}
+                       for (r = savintregcnt - 1; r >= maxsavintreguse; r--)
+                                       {p--; M_LLD(savintregs[r], REG_SP, 8 * p);}
+                       for (r = savfltregcnt - 1; r >= maxsavfltreguse; r--)
+                                       {p--; M_DLD(savfltregs[r], REG_SP, 8 * p);}
+
+                       if (parentargs_base)
+                               {M_LDA(REG_SP, REG_SP, parentargs_base*8);}
+                       if (runverbose) {
+                               M_LDA (REG_SP, REG_SP, -24);
+                               M_LST(REG_RA, REG_SP, 0);
+                               M_LST(REG_RESULT, REG_SP, 8);
+                               M_DST(REG_FRESULT, REG_SP,16);
+                               a = dseg_addaddress (method);
+                               M_LLD(argintregs[0], REG_PV, a);
+                               M_OR(REG_RESULT, REG_RESULT, argintregs[1], 0);
+                               M_FLTMOVE(REG_FRESULT, argfltregs[2]);
+                               a = dseg_addaddress ((void*) (builtin_displaymethodstop));
+                               M_LLD(REG_PV, REG_PV, a);
+                               M_JSR (REG_RA, REG_PV);
+                               s1 = (int)((u1*) mcodeptr - mcodebase);
+                               if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
+                               else {
+                                       s4 ml=-s1, mh=0;
+                                       while (ml<-32768) { ml+=65536; mh--; }
+                                       M_LDA (REG_PV, REG_RA, ml );
+                                       M_LDAH (REG_PV, REG_PV, mh );
+                                       }
+                               M_DLD(REG_FRESULT, REG_SP,16);
+                               M_LLD(REG_RESULT, REG_SP, 8);
+                               M_LLD(REG_RA, REG_SP, 0);
+                               M_LDA (REG_SP, REG_SP, 24);
+                               }
+                       M_RET(REG_ZERO, REG_RA);
+                       ALIGNCODENOP;
+                       }
+                       break;
+
+
+               case ICMD_TABLESWITCH:
+                       {
+                       s4 i, l, *s4ptr;
+
+                       s4ptr = iptr->val.a;
+                       l = s4ptr[1];                          /* low     */
+                       i = s4ptr[2];                          /* high    */
+                       
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       if (l == 0)
+                               {M_INTMOVE(s1, REG_ITMP1);}
+                       else
+                               M_LDA(REG_ITMP1, s1, -l);
+                       i = i - l + 1;
+
+                       if (i <= 256)
+                               M_CMPULE(REG_ITMP1, i - 1, REG_ITMP2, 1);
+                       else {
+                               M_LDA(REG_ITMP2, REG_ZERO, i - 1);
+                               M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2, 0);
+                               }
+                       M_BEQZ(REG_ITMP2, 0);
+                       mcode_addreference(BlockPtrOfPC(s4ptr[0]), mcodeptr);
+
+                       /* build jump table top down and use address of lowest entry */
+
+                       s4ptr += 3 + i;
+                       while (--i >= 0) {
+                               dseg_addtarget(BlockPtrOfPC(*--s4ptr));
+                               }
+                       }
+
+                       /* length of dataseg after last dseg_addtarget is used by load */
+
+                       M_S8ADDQ(REG_ITMP1, REG_PV, REG_ITMP2, 0);
+                       M_LLD(REG_ITMP2, REG_ITMP2, -dseglen);
+                       M_JMP(REG_ZERO, REG_ITMP2);
+                       ALIGNCODENOP;
+                       break;
+
+
+               case ICMD_LOOKUPSWITCH:
+                       {
+                       s4 i, l, val, *s4ptr;
+
+                       s4ptr = iptr->val.a;
+                       l = s4ptr[0];                          /* default  */
+                       i = s4ptr[1];                          /* count    */
+                       
+                       MCODECHECK((i<<2)+8);
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       while (--i >= 0) {
+                               s4ptr += 2;
+                               val = s4ptr[0];
+                               if ((val >= 0) && (val <= 255)) {
+                                       M_CMPEQ(s1, val, REG_ITMP2, 1);
+                                       }
+                               else {
+                                       if ((val >= -32768) && (val <= 32767)) {
+                                               M_LDA(REG_ITMP2, REG_ZERO, val);
+                                               } 
+                                       else {
+                                               a = dseg_adds4 (val);
+                                               M_ILD(REG_ITMP2, REG_PV, a);
+                                               }
+                                       M_CMPEQ(s1, REG_ITMP2, REG_ITMP2, 0);
+                                       }
+                               M_BNEZ(REG_ITMP2, 0);
+                               mcode_addreference(BlockPtrOfPC(s4ptr[1]), mcodeptr);
+                               }
+
+                       M_BR(0);
+                       mcode_addreference(BlockPtrOfPC(l), mcodeptr);
+                       ALIGNCODENOP;
+                       break;
+                       }
+
+
+               case ICMD_BUILTIN3:
+                       s3 = 3;
+                       goto gen_method;
+
+               case ICMD_BUILTIN2:
+                       s3 = 2;
+                       goto gen_method;
+
+               case ICMD_BUILTIN1:
+                       s3 = 1;
+                       goto gen_method;
+
+               case ICMD_INVOKESTATIC:
+               case ICMD_INVOKESPECIAL:
+               case ICMD_INVOKEVIRTUAL:
+               case ICMD_INVOKEINTERFACE:
+                       s3 = iptr->op1;
+
+gen_method: {
+                       methodinfo   *m;
+                       classinfo    *ci;
+
+                       MCODECHECK((s3 << 1) + 64);
+
+                       for (; --s3 >= 0; src = src->prev) {
+                               if (src->varkind == ARGVAR)
+                                       continue;
+                               if (IS_INT_LNG_TYPE(src->type)) {
+                                       if (s3 < INT_ARG_CNT) {
+                                               s1 = argintregs[s3];
+                                               var_to_reg_int(d, src, s1);
+                                               M_INTMOVE(d, s1);
+                                               }
+                                       else  {
+                                               var_to_reg_int(d, src, REG_ITMP1);
+                                               M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
+                                               }
+                                       }
+                               else
+                                       if (s3 < FLT_ARG_CNT) {
+                                               s1 = argfltregs[s3];
+                                               var_to_reg_flt(d, src, s1);
+                                               M_FLTMOVE(d, s1);
+                                               }
+                                       else {
+                                               var_to_reg_flt(d, src, REG_FTMP1);
+                                               M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
+                                               }
+                               } /* end of for */
+
+                       m = iptr->val.a;
+                       switch (iptr->opc) {
+                               case ICMD_BUILTIN3:
+                               case ICMD_BUILTIN2:
+                               case ICMD_BUILTIN1:
+                                       a = dseg_addaddress ((void*) (m));
+
+                                       M_LLD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
+                                       d = iptr->op1;
+                                       goto makeactualcall;
+
+                               case ICMD_INVOKESTATIC:
+                               case ICMD_INVOKESPECIAL:
+                                       a = dseg_addaddress (m->stubroutine);
+
+                                       M_LLD(REG_PV, REG_PV, a );       /* Method-Pointer in r27 */
+
+                                       d = m->returntype;
+                                       goto makeactualcall;
+
+                               case ICMD_INVOKEVIRTUAL:
+
+                                       gen_nullptr_check(argintregs[0]);
+                                       M_LLD(REG_METHODPTR, argintregs[0],
+                                                                OFFSET(java_objectheader, vftbl));
+                                       M_LLD(REG_PV, REG_METHODPTR, OFFSET(vftbl, table[0]) +
+                                                               sizeof(methodptr) * m->vftblindex);
+
+                                       d = m->returntype;
+                                       goto makeactualcall;
+
+                               case ICMD_INVOKEINTERFACE:
+                                       ci = m->class;
+                                       
+                                       gen_nullptr_check(argintregs[0]);
+                                       M_LLD(REG_METHODPTR, argintregs[0],
+                                                                OFFSET(java_objectheader, vftbl));    
+                                       M_LLD(REG_METHODPTR, REG_METHODPTR,
+                                                                   OFFSET(vftbl, interfacevftbl));
+                                       M_LLD(REG_METHODPTR, REG_METHODPTR,
+                                                                  sizeof(methodptr*) * ci->index);
+                                       M_LLD(REG_PV, REG_METHODPTR,
+                                                           sizeof(methodptr) * (m - ci->methods));
+
+                                       d = m->returntype;
+                                       goto makeactualcall;
+
+                               default:
+                                       d = 0;
+                                       sprintf (logtext, "Unkown ICMD-Command: %d", iptr->opc);
+                                       error ();
+                               }
+
+makeactualcall:
+
+                       M_JSR (REG_RA, REG_PV);
+                       s1 = (int)((u1*) mcodeptr - mcodebase);
+                       if (s1<=32768) M_LDA (REG_PV, REG_RA, -s1);
+                       else {
+                               s4 ml=-s1, mh=0;
+                               while (ml<-32768) { ml+=65536; mh--; }
+                               M_LDA (REG_PV, REG_RA, ml );
+                               M_LDAH (REG_PV, REG_PV, mh );
+                               }
+
+                       if (d != TYPE_VOID) {
+                               if (IS_INT_LNG_TYPE(iptr->dst->type)) {
+                                       s1 = reg_of_var(iptr->dst, REG_RESULT);
+                                       M_INTMOVE(REG_RESULT, s1);
+                                       store_reg_to_var_int(iptr->dst, s1);
+                                       }
+                               else {
+                                       s1 = reg_of_var(iptr->dst, REG_FRESULT);
+                                       M_FLTMOVE(REG_FRESULT, s1);
+                                       store_reg_to_var_flt(iptr->dst, s1);
+                                       }
+                               }
+                       }
+                       break;
+
+               case ICMD_CHECKASIZE:
+                       var_to_reg_int(s1, src, REG_ITMP1);
+                       M_BLTZ(s1, 0);
+                       mcode_addxcheckarefs(mcodeptr);
+                       break;
+
+               case ICMD_MULTIANEWARRAY:
+
+                       /* check for negative sizes and copy sizes to stack if necessary  */
+
+                       MCODECHECK((iptr->op1 << 1) + 64);
+
+                       for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
+                               var_to_reg_int(s2, src, REG_ITMP1);
+                               M_BLTZ(s2, 0);
+                               mcode_addxcheckarefs(mcodeptr);
+
+                               /* copy sizes to stack (argument numbers >= INT_ARG_CNT)      */
+
+                               if (src->varkind != ARGVAR) {
+                                       M_LST(s2, REG_SP, 8 * (s1 + INT_ARG_CNT));
+                                       }
+                               }
+
+                       /* a0 = dimension count */
+
+                       M_LDA(argintregs[0], REG_ZERO, iptr->op1);
+
+                       /* a1 = arraydescriptor */
+
+                       a = dseg_addaddress(iptr->val.a);
+                       M_LLD(argintregs[1], REG_PV, a);
+
+                       /* a2 = pointer to dimensions = stack pointer */
+
+                       M_INTMOVE(REG_SP, argintregs[2]);
+
+                       a = dseg_addaddress((void*) (builtin_nmultianewarray));
+                       M_LLD(REG_PV, REG_PV, a);
+                       M_JSR(REG_RA, REG_PV);
+                       s1 = (int)((u1*) mcodeptr - mcodebase);
+                       if (s1 <= 32768)
+                               M_LDA (REG_PV, REG_RA, -s1);
+                       else {
+                               s4 ml = -s1, mh = 0;
+                               while (ml < -32768) {ml += 65536; mh--;}
+                               M_LDA(REG_PV, REG_RA, ml);
+                               M_LDAH(REG_PV, REG_PV, mh);
+                               }
+                       s1 = reg_of_var(iptr->dst, REG_RESULT);
+                       M_INTMOVE(REG_RESULT, s1);
+                       store_reg_to_var_int(iptr->dst, s1);
+                       break;
+
+
+               default: sprintf (logtext, "Unknown pseudo command: %d", iptr->opc);
+                        error();
+       } /* switch */
+       } /* for instruction */
+       src = bptr->outstack;
+       len = bptr->outdepth;
+       MCODECHECK(64+len);
+       while (src) {
+               len--;
+               if ((src->varkind != STACKVAR)) {
+                       s2 = src->type;
+                       if (IS_FLT_DBL_TYPE(s2)) {
+                               var_to_reg_int(s1, src, REG_ITMP1);
+                               if (!(interfaces[len][s2].flags & INMEMORY)) {
+                                       M_FLTMOVE(s1,interfaces[len][s2].regoff);
+                                       }
+                               else {
+                                       M_DST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
+                                       }
+                               }
+                       else {
+                               var_to_reg_flt(s1, src, REG_FTMP1);
+                               if (!(interfaces[len][s2].flags & INMEMORY)) {
+                                       M_INTMOVE(s1,interfaces[len][s2].regoff);
+                                       }
+                               else {
+                                       M_LST(s1, REG_SP, 8 * interfaces[len][s2].regoff);
+                                       }
+                               }
+                       }
+               src = src->prev;
+               }
+       } /* for basic block */
+
+       {
+       s4 *xcodeptr = NULL;
+       
+       for (; xboundrefs != NULL; xboundrefs = xboundrefs->next) {
+               if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+                       gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos, 
+                               xboundrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+                       continue;
+                       }
+
+               gen_resolvebranch((u1*) mcodebase + xboundrefs->branchpos, 
+                                 xboundrefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+               MCODECHECK(8);
+
+               M_LDA(REG_ITMP2_XPC, REG_PV, xboundrefs->branchpos);
+
+               if (xcodeptr != NULL) {
+                       M_BR((xcodeptr-mcodeptr)-1);
+                       }
+               else {
+                       xcodeptr = mcodeptr;
+
+                       a = dseg_addaddress(proto_java_lang_ArrayIndexOutOfBoundsException);
+                       M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+                       a = dseg_addaddress(asm_handle_exception);
+                       M_LLD(REG_ITMP3, REG_PV, a);
+
+                       M_JMP(REG_ZERO, REG_ITMP3);
+                       }
+               }
+
+       xcodeptr = NULL;
+       
+       for (; xcheckarefs != NULL; xcheckarefs = xcheckarefs->next) {
+               if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+                       gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos, 
+                               xcheckarefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+                       continue;
+                       }
+
+               gen_resolvebranch((u1*) mcodebase + xcheckarefs->branchpos, 
+                                 xcheckarefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+               MCODECHECK(8);
+
+               M_LDA(REG_ITMP2_XPC, REG_PV, xcheckarefs->branchpos);
+
+               if (xcodeptr != NULL) {
+                       M_BR((xcodeptr-mcodeptr)-1);
+                       }
+               else {
+                       xcodeptr = mcodeptr;
+
+                       a = dseg_addaddress(proto_java_lang_NegativeArraySizeException);
+                       M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+                       a = dseg_addaddress(asm_handle_exception);
+                       M_LLD(REG_ITMP3, REG_PV, a);
+
+                       M_JMP(REG_ZERO, REG_ITMP3);
+                       }
+               }
+
+
+#ifdef SOFTNULLPTRCHECK
+
+       xcodeptr = NULL;
+
+       for (; xnullrefs != NULL; xnullrefs = xnullrefs->next) {
+               if ((exceptiontablelength == 0) && (xcodeptr != NULL)) {
+                       gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos, 
+                               xnullrefs->branchpos, (u1*) xcodeptr - (u1*) mcodebase - 4);
+                       continue;
+                       }
+
+               gen_resolvebranch((u1*) mcodebase + xnullrefs->branchpos, 
+                                 xnullrefs->branchpos, (u1*) mcodeptr - mcodebase);
+
+               MCODECHECK(8);
+
+               M_LDA(REG_ITMP2_XPC, REG_PV, xnullrefs->branchpos - 4);
+
+               if (xcodeptr != NULL) {
+                       M_BR((xcodeptr-mcodeptr)-1);
+                       }
+               else {
+                       xcodeptr = mcodeptr;
+
+                       a = dseg_addaddress(proto_java_lang_NullPointerException);
+                       M_LLD(REG_ITMP1_XPTR, REG_PV, a);
+
+                       a = dseg_addaddress(asm_handle_exception);
+                       M_LLD(REG_ITMP3, REG_PV, a);
+
+                       M_JMP(REG_ZERO, REG_ITMP3);
+                       }
+               }
+
+#endif
+       }
+
+       mcode_finish((int)((u1*) mcodeptr - mcodebase));
+}
+
+
+/******** redefinition of code generation macros (compiling into array) *******/
+
+/* 
+These macros are newly defined to allow code generation into an array.
+This is necessary, because the original M_.. macros generate code by
+calling 'mcode_adds4' that uses an additional data structure to
+receive the code.
+
+For a faster (but less flexible) version to generate code, these
+macros directly use the (s4* p) - pointer to put the code directly
+in a locally defined array.
+This makes sense only for the stub-generation-routines below.
+*/
+
+#undef M_OP3
+#define M_OP3(op,fu,a,b,c,const) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+       ((const)<<12)|((fu)<<5)|((c)) )
+#undef M_FOP3
+#define M_FOP3(op,fu,a,b,c) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+#undef M_BRA
+#define M_BRA(op,a,disp) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+#undef M_MEM
+#define M_MEM(op,a,b,disp) \
+       *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+#if 0
+
+/************************ function createcompilerstub **************************
+
+       creates a stub routine which calls the compiler
+       
+*******************************************************************************/
+
+#define COMPSTUBSIZE 3
+
+u1 *createcompilerstub (methodinfo *m)
+{
+       u8 *s = CNEW (u8, COMPSTUBSIZE);    /* memory to hold the stub            */
+       s4 *p = (s4*) s;                    /* code generation pointer            */
+       
+                                           /* code for the stub                  */
+       M_LLD (REG_PV, REG_PV, 16);         /* load pointer to the compiler       */
+       M_JMP (0, REG_PV);                  /* jump to the compiler, return address
+                                              in reg 0 is used as method pointer */
+       s[1] = (u8) m;                      /* literals to be adressed            */  
+       s[2] = (u8) asm_call_jit_compiler;  /* jump directly via PV from above    */
+
+#ifdef STATISTICS
+       count_cstub_len += COMPSTUBSIZE * 8;
+#endif
+
+       return (u1*) s;
+}
+
+
+/************************* function removecompilerstub *************************
+
+     deletes a compilerstub from memory  (simply by freeing it)
+
+*******************************************************************************/
+
+void removecompilerstub (u1 *stub) 
+{
+       CFREE (stub, COMPSTUBSIZE * 8);
+}
+
+
+/************************ function: removenativestub ***************************
+
+    removes a previously created native-stub from memory
+    
+*******************************************************************************/
+
+void removenativestub (u1 *stub)
+{
+       CFREE (stub, NATIVESTUBSIZE * 8);
+}
+
+#endif /* 0 */
+
+
+/********************* Funktion: ncreatenativestub *****************************
+
+       creates a stub routine which calls a native method
+       
+*******************************************************************************/
+
+#define NATIVESTUBSIZE 11
+
+u1 *ncreatenativestub (functionptr f, methodinfo *m)
+{
+       u8 *s = CNEW (u8, NATIVESTUBSIZE);  /* memory to hold the stub            */
+       s4 *p = (s4*) s;                    /* code generation pointer            */
+
+       M_LDA  (REG_SP, REG_SP, -8);        /* build up stackframe                */
+       M_LST  (REG_RA, REG_SP, 0);         /* store return address               */
+
+       M_LLD  (REG_PV, REG_PV, 8*8);       /* load adress of native method       */
+       M_JSR  (REG_RA, REG_PV);            /* call native method                 */
+
+       M_LDA  (REG_PV, REG_RA, -4*4);      /* recompute pv from ra               */
+       M_LLD  (REG_ITMP3, REG_PV, 9*8);    /* get address of exceptionptr        */
+
+       M_LLD  (REG_RA, REG_SP, 0);         /* load return address                */
+       M_LLD  (REG_ITMP1, REG_ITMP3, 0);   /* load exception into reg. itmp1     */
+
+       M_LDA  (REG_SP, REG_SP, 8);         /* remove stackframe                  */
+       M_BNEZ (REG_ITMP1, 1);              /* if no exception then return        */
+
+       M_RET  (REG_ZERO, REG_RA);          /* return to caller                   */
+       
+       M_LST  (REG_ZERO, REG_ITMP3, 0);    /* store NULL into exceptionptr       */
+       M_LDA  (REG_ITMP2, REG_RA, -4);     /* move fault address into reg. itmp2 */
+
+       M_LLD  (REG_ITMP3, REG_PV,10*8);    /* load asm exception handler address */
+       M_JMP  (REG_ZERO, REG_ITMP3);       /* jump to asm exception handler      */
+
+
+       s[8] = (u8) f;                      /* address of native method           */
+       s[9] = (u8) (&exceptionptr);        /* address of exceptionptr            */
+       s[10]= (u8) (asm_handle_nat_exception); /* addr of asm exception handler  */
+
+#ifdef STATISTICS
+       count_nstub_len += NATIVESTUBSIZE * 8;
+#endif
+
+       return (u1*) s;
+}
+
diff --git a/alpha/ngen.h b/alpha/ngen.h
new file mode 100644 (file)
index 0000000..5b3239c
--- /dev/null
@@ -0,0 +1,328 @@
+/***************************** alpha/ngen.h ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the machine dependent code generator definitions and macros for an
+       Alpha processor.
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/08/10
+
+*******************************************************************************/
+
+/************************ Preallocated registers ******************************/
+
+/* integer registers */
+  
+#define REG_RESULT      0    /* to deliver method results                     */ 
+#define REG_EXCEPTION          1    /* to throw an exception across method bounds    */
+
+#define REG_RA          26   /* return address                                */
+#define REG_PV          27   /* procedure vector, must be provided by caller  */
+#define REG_METHODPTR   28   /* pointer to the place from where the procedure */
+                             /* vector has been fetched                       */
+#define REG_ITMP1       25   /* temporary register                            */
+#define REG_ITMP2       28   /* temporary register                            */
+#define REG_ITMP3       29   /* temporary register                            */
+
+#define REG_ITMP1_XPTR  25   /* exception pointer = temporary register 1      */
+#define REG_ITMP2_XPC   28   /* exception pc = temporary register 2           */
+
+#define REG_SP          30   /* stack pointer                                 */
+#define REG_ZERO        31   /* allways zero                                  */
+
+/* floating point registers */
+
+#define REG_FRESULT     0    /* to deliver floating point method results      */ 
+#define REG_FTMP1       28   /* temporary floating point register             */
+#define REG_FTMP2       29   /* temporary floating point register             */
+#define REG_FTMP3       30   /* temporary floating point register             */
+
+#define REG_IFTMP       28   /* temporary integer and floating point register */
+
+/******************** register descripton - array *****************************/
+
+/* #define REG_RES   0         reserved register for OS or code generator */
+/* #define REG_RET   1         return value register */
+/* #define REG_EXC   2         exception value register */
+/* #define REG_SAV   3         (callee) saved register */
+/* #define REG_TMP   4         scratch temporary register (caller saved) */
+/* #define REG_ARG   5         argument register (caller saved) */
+
+/* #define REG_END   -1        last entry in tables */
+int nregdescint[] = {
+       REG_RET, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, 
+       REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, 
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+       REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
+       REG_END };
+
+#define INT_SAV_CNT      7   /* number of int callee saved registers          */
+#define INT_ARG_CNT      6   /* number of int argument registers              */
+
+/* for use of reserved registers, see comment above */
+       
+int nregdescfloat[] = {
+       REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
+       REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, 
+       REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
+       REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
+       REG_END };
+
+#define FLT_SAV_CNT      8   /* number of flt callee saved registers          */
+#define FLT_ARG_CNT      6   /* number of flt argument registers              */
+
+/* for use of reserved registers, see comment above */
+
+
+/*** parameter allocation mode ***/
+
+int nreg_parammode = PARAMMODE_NUMBERED;  
+
+   /* parameter-registers will be allocated by assigning the
+      1. parameter:   int/float-reg 16
+      2. parameter:   int/float-reg 17  
+      3. parameter:   int/float-reg 18 ....
+   */
+
+
+/************************** stackframe-infos **********************************/
+
+int parentargs_base; /* offset in stackframe for the parameter from the caller*/
+
+/* -> see file 'calling.doc' */
+
+
+/******************** macros to create code ***********************************/
+
+/* 3-address-operations: M_OP3
+      op ..... opcode
+      fu ..... function-number
+      a  ..... register number source 1
+      b  ..... register number or constant integer source 2
+      c  ..... register number destination
+      const .. switch to use b as constant integer 
+                 (0 means: use b as register number)
+                 (1 means: use b as constant 8-bit-integer)
+*/      
+#define M_OP3(op,fu,a,b,c,const) \
+       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
+       ((const)<<12)|((fu)<<5)|((c)) )
+
+/* 3-address-floating-point-operation: M_FOP3 
+     op .... opcode
+     fu .... function-number
+     a,b ... source floating-point registers
+     c ..... destination register
+*/ 
+#define M_FOP3(op,fu,a,b,c) \
+       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
+
+/* branch instructions: M_BRA 
+      op ..... opcode
+      a ...... register to be tested
+      disp ... relative address to be jumped to (divided by 4)
+*/
+#define M_BRA(op,a,disp) \
+       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
+
+
+/* memory operations: M_MEM
+      op ..... opcode
+      a ...... source/target register for memory access
+      b ...... base register
+      disp ... displacement (16 bit signed) to be added to b
+*/ 
+#define M_MEM(op,a,b,disp) \
+       *(mcodeptr++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
+
+
+/***** macros for all used commands (see an Alpha-manual for description) *****/ 
+
+#define M_LDA(a,b,disp)         M_MEM (0x08,a,b,disp)           /* low const  */
+#define M_LDAH(a,b,disp)        M_MEM (0x09,a,b,disp)           /* high const */
+#define M_BLDU(a,b,disp)        M_MEM (0x0a,a,b,disp)           /*  8 load    */
+#define M_SLDU(a,b,disp)        M_MEM (0x0c,a,b,disp)           /* 16 load    */
+#define M_ILD(a,b,disp)         M_MEM (0x28,a,b,disp)           /* 32 load    */
+#define M_LLD(a,b,disp)         M_MEM (0x29,a,b,disp)           /* 64 load    */
+#define M_BST(a,b,disp)         M_MEM (0x0e,a,b,disp)           /*  8 store   */
+#define M_SST(a,b,disp)         M_MEM (0x0d,a,b,disp)           /* 16 store   */
+#define M_IST(a,b,disp)         M_MEM (0x2c,a,b,disp)           /* 32 store   */
+#define M_LST(a,b,disp)         M_MEM (0x2d,a,b,disp)           /* 64 store   */
+
+#define M_BSEXT(b,c)            M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /*  8 signext */
+#define M_SSEXT(b,c)            M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
+
+#define M_BR(disp)              M_BRA (0x30,REG_ZERO,disp)      /* branch     */
+#define M_BSR(ra,disp)          M_BRA (0x34,ra,disp)            /* branch sbr */
+#define M_BEQZ(a,disp)          M_BRA (0x39,a,disp)             /* br a == 0  */
+#define M_BLTZ(a,disp)          M_BRA (0x3a,a,disp)             /* br a <  0  */
+#define M_BLEZ(a,disp)          M_BRA (0x3b,a,disp)             /* br a <= 0  */
+#define M_BNEZ(a,disp)          M_BRA (0x3d,a,disp)             /* br a != 0  */
+#define M_BGEZ(a,disp)          M_BRA (0x3e,a,disp)             /* br a >= 0  */
+#define M_BGTZ(a,disp)          M_BRA (0x3f,a,disp)             /* br a >  0  */
+
+#define M_JMP(a,b)              M_MEM (0x1a,a,b,0x0000)         /* jump       */
+#define M_JSR(a,b)              M_MEM (0x1a,a,b,0x4000)         /* call sbr   */
+#define M_RET(a,b)              M_MEM (0x1a,a,b,0x8000)         /* return     */
+
+#define M_IADD(a,b,c,const)     M_OP3 (0x10,0x0,  a,b,c,const)  /* 32 add     */
+#define M_LADD(a,b,c,const)     M_OP3 (0x10,0x20, a,b,c,const)  /* 64 add     */
+#define M_ISUB(a,b,c,const)     M_OP3 (0x10,0x09, a,b,c,const)  /* 32 sub     */
+#define M_LSUB(a,b,c,const)     M_OP3 (0x10,0x29, a,b,c,const)  /* 64 sub     */
+#define M_IMUL(a,b,c,const)     M_OP3 (0x13,0x00, a,b,c,const)  /* 32 mul     */
+#define M_LMUL(a,b,c,const)     M_OP3 (0x13,0x20, a,b,c,const)  /* 64 mul     */
+
+#define M_CMPEQ(a,b,c,const)    M_OP3 (0x10,0x2d, a,b,c,const)  /* c = a == b */
+#define M_CMPLT(a,b,c,const)    M_OP3 (0x10,0x4d, a,b,c,const)  /* c = a <  b */
+#define M_CMPLE(a,b,c,const)    M_OP3 (0x10,0x6d, a,b,c,const)  /* c = a <= b */
+
+#define M_CMPULE(a,b,c,const)   M_OP3 (0x10,0x3d, a,b,c,const)  /* c = a <= b */
+#define M_CMPULT(a,b,c,const)   M_OP3 (0x10,0x1d, a,b,c,const)  /* c = a <= b */
+
+#define M_AND(a,b,c,const)      M_OP3 (0x11,0x00, a,b,c,const)  /* c = a &  b */
+#define M_OR(a,b,c,const)       M_OP3 (0x11,0x20, a,b,c,const)  /* c = a |  b */
+#define M_XOR(a,b,c,const)      M_OP3 (0x11,0x40, a,b,c,const)  /* c = a ^  b */
+
+#define M_NOP                   M_OR (31,31,31,0)
+
+#define M_SLL(a,b,c,const)      M_OP3 (0x12,0x39, a,b,c,const)  /* c = a << b */
+#define M_SRA(a,b,c,const)      M_OP3 (0x12,0x3c, a,b,c,const)  /* c = a >> b */
+#define M_SRL(a,b,c,const)      M_OP3 (0x12,0x34, a,b,c,const)  /* c = a >>>b */
+
+#define M_FLD(a,b,disp)         M_MEM (0x22,a,b,disp)           /* load flt   */
+#define M_DLD(a,b,disp)         M_MEM (0x23,a,b,disp)           /* load dbl   */
+#define M_FST(a,b,disp)         M_MEM (0x26,a,b,disp)           /* store flt  */
+#define M_DST(a,b,disp)         M_MEM (0x27,a,b,disp)           /* store dbl  */
+
+#define M_FADD(a,b,c)           M_FOP3 (0x16, 0x080, a,b,c)     /* flt add    */
+#define M_DADD(a,b,c)           M_FOP3 (0x16, 0x0a0, a,b,c)     /* dbl add    */
+#define M_FSUB(a,b,c)           M_FOP3 (0x16, 0x081, a,b,c)     /* flt sub    */
+#define M_DSUB(a,b,c)           M_FOP3 (0x16, 0x0a1, a,b,c)     /* dbl sub    */
+#define M_FMUL(a,b,c)           M_FOP3 (0x16, 0x082, a,b,c)     /* flt mul    */
+#define M_DMUL(a,b,c)           M_FOP3 (0x16, 0x0a2, a,b,c)     /* dbl mul    */
+#define M_FDIV(a,b,c)           M_FOP3 (0x16, 0x083, a,b,c)     /* flt div    */
+#define M_DDIV(a,b,c)           M_FOP3 (0x16, 0x0a3, a,b,c)     /* dbl div    */
+
+#define M_FADDS(a,b,c)          M_FOP3 (0x16, 0x580, a,b,c)     /* flt add    */
+#define M_DADDS(a,b,c)          M_FOP3 (0x16, 0x5a0, a,b,c)     /* dbl add    */
+#define M_FSUBS(a,b,c)          M_FOP3 (0x16, 0x581, a,b,c)     /* flt sub    */
+#define M_DSUBS(a,b,c)          M_FOP3 (0x16, 0x5a1, a,b,c)     /* dbl sub    */
+#define M_FMULS(a,b,c)          M_FOP3 (0x16, 0x582, a,b,c)     /* flt mul    */
+#define M_DMULS(a,b,c)          M_FOP3 (0x16, 0x5a2, a,b,c)     /* dbl mul    */
+#define M_FDIVS(a,b,c)          M_FOP3 (0x16, 0x583, a,b,c)     /* flt div    */
+#define M_DDIVS(a,b,c)          M_FOP3 (0x16, 0x5a3, a,b,c)     /* dbl div    */
+
+#define M_CVTDF(a,b,c)          M_FOP3 (0x16, 0x0ac, a,b,c)     /* dbl2long   */
+#define M_CVTLF(a,b,c)          M_FOP3 (0x16, 0x0bc, a,b,c)     /* long2flt   */
+#define M_CVTLD(a,b,c)          M_FOP3 (0x16, 0x0be, a,b,c)     /* long2dbl   */
+#define M_CVTDL(a,b,c)          M_FOP3 (0x16, 0x1af, a,b,c)     /* dbl2long   */
+#define M_CVTDL_C(a,b,c)        M_FOP3 (0x16, 0x12f, a,b,c)     /* dbl2long   */
+#define M_CVTLI(a,b)            M_FOP3 (0x17, 0x130, 31,a,b)    /* long2int   */
+
+#define M_CVTDFS(a,b,c)         M_FOP3 (0x16, 0x5ac, a,b,c)     /* dbl2long   */
+#define M_CVTDLS(a,b,c)         M_FOP3 (0x16, 0x5af, a,b,c)     /* dbl2long   */
+#define M_CVTDL_CS(a,b,c)       M_FOP3 (0x16, 0x52f, a,b,c)     /* dbl2long   */
+#define M_CVTLIS(a,b)           M_FOP3 (0x17, 0x530, 31,a,b)    /* long2int   */
+
+#define M_FCMPEQ(a,b,c)         M_FOP3 (0x16, 0x0a5, a,b,c)     /* c = a==b   */
+#define M_FCMPLT(a,b,c)         M_FOP3 (0x16, 0x0a6, a,b,c)     /* c = a<b    */
+
+#define M_FCMPEQS(a,b,c)        M_FOP3 (0x16, 0x5a5, a,b,c)     /* c = a==b   */
+#define M_FCMPLTS(a,b,c)        M_FOP3 (0x16, 0x5a6, a,b,c)     /* c = a<b    */
+
+#define M_FMOV(fa,fb)           M_FOP3 (0x17, 0x020, fa,fa,fb)  /* b = a      */
+#define M_FMOVN(fa,fb)          M_FOP3 (0x17, 0x021, fa,fa,fb)  /* b = -a     */
+
+#define M_FNOP                  M_FMOV (31,31)
+
+#define M_FBEQZ(fa,disp)        M_BRA (0x31,fa,disp)            /* br a == 0.0*/
+
+/****** macros for special commands (see an Alpha-manual for description) *****/ 
+
+#define M_TRAPB                 M_MEM (0x18,0,0,0x0000)        /* trap barrier*/
+
+#define M_S4ADDL(a,b,c,const)   M_OP3 (0x10,0x02, a,b,c,const) /* c = a*4 + b */
+#define M_S4ADDQ(a,b,c,const)   M_OP3 (0x10,0x22, a,b,c,const) /* c = a*4 + b */
+#define M_S4SUBL(a,b,c,const)   M_OP3 (0x10,0x0b, a,b,c,const) /* c = a*4 - b */
+#define M_S4SUBQ(a,b,c,const)   M_OP3 (0x10,0x2b, a,b,c,const) /* c = a*4 - b */
+#define M_S8ADDL(a,b,c,const)   M_OP3 (0x10,0x12, a,b,c,const) /* c = a*8 + b */
+#define M_S8ADDQ(a,b,c,const)   M_OP3 (0x10,0x32, a,b,c,const) /* c = a*8 + b */
+#define M_S8SUBL(a,b,c,const)   M_OP3 (0x10,0x1b, a,b,c,const) /* c = a*8 - b */
+#define M_S8SUBQ(a,b,c,const)   M_OP3 (0x10,0x3b, a,b,c,const) /* c = a*8 - b */
+
+#define M_LLD_U(a,b,disp)       M_MEM (0x0b,a,b,disp)          /* unalign ld  */
+#define M_LST_U(a,b,disp)       M_MEM (0x0f,a,b,disp)          /* unalign st  */
+
+#define M_ZAP(a,b,c,const)      M_OP3 (0x12,0x30, a,b,c,const)
+#define M_ZAPNOT(a,b,c,const)   M_OP3 (0x12,0x31, a,b,c,const)
+#define M_EXTBL(a,b,c,const)    M_OP3 (0x12,0x06, a,b,c,const)
+#define M_EXTWL(a,b,c,const)    M_OP3 (0x12,0x16, a,b,c,const)
+#define M_EXTLL(a,b,c,const)    M_OP3 (0x12,0x26, a,b,c,const)
+#define M_EXTQL(a,b,c,const)    M_OP3 (0x12,0x36, a,b,c,const)
+#define M_EXTWH(a,b,c,const)    M_OP3 (0x12,0x5a, a,b,c,const)
+#define M_EXTLH(a,b,c,const)    M_OP3 (0x12,0x6a, a,b,c,const)
+#define M_EXTQH(a,b,c,const)    M_OP3 (0x12,0x7a, a,b,c,const)
+#define M_INSBL(a,b,c,const)    M_OP3 (0x12,0x0b, a,b,c,const)
+#define M_INSWL(a,b,c,const)    M_OP3 (0x12,0x1b, a,b,c,const)
+#define M_INSLL(a,b,c,const)    M_OP3 (0x12,0x2b, a,b,c,const)
+#define M_INSQL(a,b,c,const)    M_OP3 (0x12,0x3b, a,b,c,const)
+#define M_INSWH(a,b,c,const)    M_OP3 (0x12,0x57, a,b,c,const)
+#define M_INSLH(a,b,c,const)    M_OP3 (0x12,0x67, a,b,c,const)
+#define M_INSQH(a,b,c,const)    M_OP3 (0x12,0x77, a,b,c,const)
+#define M_MSKBL(a,b,c,const)    M_OP3 (0x12,0x02, a,b,c,const)
+#define M_MSKWL(a,b,c,const)    M_OP3 (0x12,0x12, a,b,c,const)
+#define M_MSKLL(a,b,c,const)    M_OP3 (0x12,0x22, a,b,c,const)
+#define M_MSKQL(a,b,c,const)    M_OP3 (0x12,0x32, a,b,c,const)
+#define M_MSKWH(a,b,c,const)    M_OP3 (0x12,0x52, a,b,c,const)
+#define M_MSKLH(a,b,c,const)    M_OP3 (0x12,0x62, a,b,c,const)
+#define M_MSKQH(a,b,c,const)    M_OP3 (0x12,0x72, a,b,c,const)
+
+
+/****** macros for unused commands (see an Alpha-manual for description) ******/ 
+
+#define M_ANDNOT(a,b,c,const)   M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b  */
+#define M_ORNOT(a,b,c,const)    M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b  */
+#define M_XORNOT(a,b,c,const)   M_OP3 (0x11,0x48, a,b,c,const) /* c = a ^~ b  */
+
+#define M_CMOVEQ(a,b,c,const)   M_OP3 (0x11,0x24, a,b,c,const) /* a==0 ? c=b  */
+#define M_CMOVNE(a,b,c,const)   M_OP3 (0x11,0x26, a,b,c,const) /* a!=0 ? c=b  */
+#define M_CMOVLT(a,b,c,const)   M_OP3 (0x11,0x44, a,b,c,const) /* a< 0 ? c=b  */
+#define M_CMOVGE(a,b,c,const)   M_OP3 (0x11,0x46, a,b,c,const) /* a>=0 ? c=b  */
+#define M_CMOVLE(a,b,c,const)   M_OP3 (0x11,0x64, a,b,c,const) /* a<=0 ? c=b  */
+#define M_CMOVGT(a,b,c,const)   M_OP3 (0x11,0x66, a,b,c,const) /* a> 0 ? c=b  */
+
+#define M_CMPBGE(a,b,c,const)   M_OP3 (0x10,0x0f, a,b,c,const)
+
+#define M_FCMPUN(a,b,c)         M_FOP3 (0x16, 0x0a4, a,b,c)    /* unordered   */
+#define M_FCMPLE(a,b,c)         M_FOP3 (0x16, 0x0a7, a,b,c)    /* c = a<=b    */
+
+#define M_FCMPUNS(a,b,c)        M_FOP3 (0x16, 0x5a4, a,b,c)    /* unordered   */
+#define M_FCMPLES(a,b,c)        M_FOP3 (0x16, 0x5a7, a,b,c)    /* c = a<=b    */
+
+#define M_FBNEZ(fa,disp)        M_BRA (0x35,fa,disp)
+#define M_FBLEZ(fa,disp)        M_BRA (0x33,fa,disp)
+
+#define M_JMP_CO(a,b)           M_MEM (0x1a,a,b,0xc000)        /* call cosub  */
+
+
+/************************ function gen_resolvebranch ***************************
+
+       backpatches a branch instruction; Alpha branch instructions are very
+       regular, so it is only necessary to overwrite some fixed bits in the
+       instruction.
+
+       parameters: ip ... pointer to instruction after branch (void*)
+                   so ... offset of instruction after branch  (s4)
+                   to ... offset of branch target             (s4)
+
+*******************************************************************************/
+
+#define gen_resolvebranch(ip,so,to) ((s4*)(ip))[-1]|=((s4)(to)-(so))>>2&0x1fffff
+
+#define SOFTNULLPTRCHECK
diff --git a/alpha/sigcontext.h b/alpha/sigcontext.h
new file mode 100644 (file)
index 0000000..2b5f1b5
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _ASMAXP_SIGCONTEXT_H
+#define _ASMAXP_SIGCONTEXT_H
+
+struct sigcontext_struct {
+
+       /*
+       * what should we have here? I'd probably better use the same
+       * stack layout as OSF/1, just in case we ever want to try
+       * running their binaries.. 
+       *
+       * This is the basic layout, but I don't know if we'll ever
+       * actually fill in all the values..
+       */
+
+       long          sc_onstack;    /* sigstack state to restore       */
+       long          sc_mask;       /* signal mask to restore          */
+       long          sc_pc;         /* pc at time of signal            */
+       long          sc_ps;         /* psl to retore                   */
+       long          sc_regs[32];   /* processor regs 0 to 31          */
+       long          sc_ownedfp;    /* fp has been used                */
+       long          sc_fpregs[32]; /* fp regs 0 to 31                 */
+       unsigned long sc_fpcr;       /* floating point control register */
+       unsigned long sc_fp_control; /* software fpcr                   */
+                                    /* rest is unused                  */
+       unsigned long sc_reserved1, sc_reserved2;
+       unsigned long sc_ssize;
+       char          *sc_sbase;
+       unsigned long sc_traparg_a0;
+       unsigned long sc_traparg_a1;
+       unsigned long sc_traparg_a2;
+       unsigned long sc_fp_trap_pc;
+       unsigned long sc_fp_trigger_sum;
+       unsigned long sc_fp_trigger_inst;
+       unsigned long sc_retcode[2];
+};
+
+#endif
diff --git a/alpha/threads.h b/alpha/threads.h
new file mode 100644 (file)
index 0000000..c2b8e86
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * i386/threads.h
+ * i386 threading information.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+ * 
+ * See file COPYRIGHT for information on usage and disclaimer of warranties
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __alpha_threads_h
+#define __alpha_threads_h
+
+/**/
+/* Thread handling */
+/**/
+
+#include "../threads/thread.h"
+
+void perform_alpha_threadswitch (u1 **from, u1 **to);
+u1* initialize_thread_stack (void *func, u1 *stack);
+u1* used_stack_top (void);
+
+#define        THREADSTACKSIZE         (64 * 1024)
+
+#define        THREADSWITCH(to, from)     perform_alpha_threadswitch(&(from)->restorePoint,\
+                                                              &(to)->restorePoint)
+
+#define THREADINIT(to, func)       (to)->restorePoint = \
+                                     initialize_thread_stack((u1*)(func), \
+                                                             (to)->stackEnd)
+
+#define USEDSTACKTOP(top)          (top) = used_stack_top()
+
+#define        THREADINFO(ee)                                          \
+               do {                                            \
+                       (ee)->restorePoint = 0;                 \
+                       (ee)->flags = THREAD_FLAGS_NOSTACKALLOC;\
+               } while(0)
+
+/*
+                       void* ptr;                              \
+                       asm("addq $30,$31,%0" : "=r" (ptr));    \
+                       (ee)->stackEnd = ptr;                   \
+                       (ee)->stackBase = (ee)->stackEnd - threadStackSize;\
+*/
+
+/*
+#define        THREADFRAMES(tid, cnt)                                  \
+               do {                                            \
+                       void** ptr;                             \
+                       cnt = 0;                                \
+                       if (tid == currentThread) {             \
+                               asm("movl %%ebp,%0" : "=r" (ptr));\
+                       }                                       \
+                       else {                                  \
+                               ptr = ((void***)tid->PrivateInfo->restorePoint)[2];\
+                       }                                       \
+                       while (*ptr != 0) {                     \
+                               cnt++;                          \
+                               ptr = (void**)*ptr;             \
+                       }                                       \
+               } while (0)
+*/
+
+#endif
diff --git a/alpha/types.h b/alpha/types.h
new file mode 100644 (file)
index 0000000..8325c8c
--- /dev/null
@@ -0,0 +1,58 @@
+/*************************** alpha/types.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       machine specific definitions for the Alpha processor
+       
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Michael Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/09/22
+
+*******************************************************************************/
+
+#ifndef _CACAO_TYPES_H
+
+#define _CACAO_TYPES_H
+
+#define POINTERSIZE         8
+#define WORDS_BIGENDIAN     0
+
+#define SUPPORT_DIVISION    0
+#define SUPPORT_LONG        1
+#define SUPPORT_FLOAT       1
+#define SUPPORT_DOUBLE      1
+
+#define SUPPORT_LONG_ADD    1
+#define SUPPORT_LONG_CMP    1
+#define SUPPORT_LONG_LOG    1
+#define SUPPORT_LONG_SHIFT  1
+#define SUPPORT_LONG_MULDIV 1
+#define SUPPORT_LONG_ICVT   1
+#define SUPPORT_LONG_FCVT   1
+
+#define U8_AVAILABLE        1
+
+
+typedef signed char             s1;
+typedef unsigned char           u1;
+typedef signed short int        s2;
+typedef unsigned short int      u2;
+
+typedef signed int              s4;
+typedef unsigned int            u4;
+
+#if U8_AVAILABLE
+typedef signed long int         s8;
+typedef unsigned long int       u8; 
+#else
+typedef struct {u4 low, high;}  u8;
+#define s8 u8
+#endif
+
+#endif
+
diff --git a/asmpart.h b/asmpart.h
new file mode 100644 (file)
index 0000000..927ccd1
--- /dev/null
+++ b/asmpart.h
@@ -0,0 +1,41 @@
+/****************************** asmpart.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Headerfile for asmpart.S. asmpart.S contains the machine dependent
+       Java - C interface functions.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/15
+
+*******************************************************************************/
+
+int has_no_x_instr_set();
+       /* determines if the byte support instruction set (21164a and higher)
+          is available. */
+
+void synchronize_caches();
+
+
+void asm_call_jit_compiler ();
+       /* invokes the compiler for untranslated JavaVM methods.
+          Register R0 contains a pointer to the method info structure
+          (prepared by createcompilerstub). */
+
+java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void*arg2,
+                                       void*arg3, void*arg4);
+       /* This function calls a Java-method (which possibly needs compilation)
+          with up to 4 parameters. This function calls a Java-method (which
+          possibly needs compilation) with up to 4 parameters. */
+
+
+void asm_dumpregistersandcall ( functionptr f);
+       /* This funtion saves all callee saved registers and calls the function
+          which is passed as parameter.
+          This function is needed by the garbage collector, which needs to access
+          all registers which are stored on the stack. Unused registers are
+          cleared to avoid interferances with the GC. */
diff --git a/builtin.c b/builtin.c
new file mode 100644 (file)
index 0000000..c1de52d
--- /dev/null
+++ b/builtin.c
@@ -0,0 +1,1621 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** builtin.c **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enthaelt die C-Funktionen fuer alle JavaVM-Befehle, die sich nicht direkt
+       auf Maschinencode "ubersetzen lassen. Im Code f"ur die Methoden steht
+       dann ein Funktionsaufruf (nat"urlich mit den Aufrufskonventionen von C).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/12/03
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <values.h>
+
+#include "global.h"
+#include "builtin.h"
+
+#include "loader.h"
+#include "tables.h"
+
+#include "threads/thread.h"
+#include "threads/locks.h"              /* schani */
+
+#include "sysdep/native-math.h"
+
+builtin_descriptor builtin_desc[] = {
+       {(functionptr) builtin_instanceof,         "instanceof"},
+       {(functionptr) builtin_checkcast,          "checkcast"},
+       {(functionptr) new_builtin_checkcast,      "checkcast"},
+       {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
+       {(functionptr) builtin_checkarraycast,     "checkarraycast"},
+       {(functionptr) new_builtin_checkarraycast, "checkarraycast"},
+       {(functionptr) new_builtin_aastore,        "aastore"},
+       {(functionptr) builtin_new,                "new"},
+       {(functionptr) builtin_anewarray,          "anewarray"},
+       {(functionptr) builtin_newarray_array,     "newarray_array"},
+       {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
+       {(functionptr) builtin_newarray_char,      "newarray_char"},
+       {(functionptr) builtin_newarray_float,     "newarray_float"},
+       {(functionptr) builtin_newarray_double,    "newarray_double"},
+       {(functionptr) builtin_newarray_byte,      "newarray_byte"},
+       {(functionptr) builtin_newarray_short,     "newarray_short"},
+       {(functionptr) builtin_newarray_int,       "newarray_int"},
+       {(functionptr) builtin_newarray_long,      "newarray_long"},
+       {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
+       {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
+       {(functionptr) builtin_monitorenter,       "monitorenter"},
+       {(functionptr) new_builtin_monitorenter,   "monitorenter"},
+       {(functionptr) builtin_monitorexit,        "monitorexit"},
+       {(functionptr) new_builtin_monitorexit,    "monitorexit"},
+       {(functionptr) builtin_idiv,               "idiv"},
+       {(functionptr) new_builtin_idiv,           "idiv"},
+       {(functionptr) builtin_irem,               "irem"},
+       {(functionptr) new_builtin_irem,           "irem"},
+       {(functionptr) builtin_ladd,               "ladd"},
+       {(functionptr) builtin_lsub,               "lsub"},
+       {(functionptr) builtin_lmul,               "lmul"},
+       {(functionptr) builtin_ldiv,               "ldiv"},
+       {(functionptr) new_builtin_ldiv,           "ldiv"},
+       {(functionptr) builtin_lrem,               "lrem"},
+       {(functionptr) new_builtin_lrem,           "lrem"},
+       {(functionptr) builtin_lshl,               "lshl"},
+       {(functionptr) builtin_lshr,               "lshr"},
+       {(functionptr) builtin_lushr,              "lushr"},
+       {(functionptr) builtin_land,               "land"},
+       {(functionptr) builtin_lor,                "lor"},
+       {(functionptr) builtin_lxor,               "lxor"},
+       {(functionptr) builtin_lneg,               "lneg"},
+       {(functionptr) builtin_lcmp,               "lcmp"},
+       {(functionptr) builtin_fadd,               "fadd"},
+       {(functionptr) builtin_fsub,               "fsub"},
+       {(functionptr) builtin_fmul,               "fmul"},
+       {(functionptr) builtin_fdiv,               "fdiv"},
+       {(functionptr) builtin_frem,               "frem"},
+       {(functionptr) builtin_fneg,               "fneg"},
+       {(functionptr) builtin_fcmpl,              "fcmpl"},
+       {(functionptr) builtin_fcmpg,              "fcmpg"},
+       {(functionptr) builtin_dadd,               "dadd"},
+       {(functionptr) builtin_dsub,               "dsub"},
+       {(functionptr) builtin_dmul,               "dmul"},
+       {(functionptr) builtin_ddiv,               "ddiv"},
+       {(functionptr) builtin_drem,               "drem"},
+       {(functionptr) builtin_dneg,               "dneg"},
+       {(functionptr) builtin_dcmpl,              "dcmpl"},
+       {(functionptr) builtin_dcmpg,              "dcmpg"},
+       {(functionptr) builtin_i2l,                "i2l"},
+       {(functionptr) builtin_i2f,                "i2f"},
+       {(functionptr) builtin_i2d,                "i2d"},
+       {(functionptr) builtin_l2i,                "l2i"},
+       {(functionptr) builtin_l2f,                "l2f"},
+       {(functionptr) builtin_l2d,                "l2d"},
+       {(functionptr) builtin_f2i,                "f2i"},
+       {(functionptr) builtin_f2l,                "f2l"},
+       {(functionptr) builtin_f2d,                "f2d"},
+       {(functionptr) builtin_d2i,                "d2i"},
+       {(functionptr) builtin_d2l,                "d2l"},
+       {(functionptr) builtin_d2f,                "d2f"},
+       {(functionptr) NULL,                       "unknown"}
+       };
+
+
+/*****************************************************************************
+                                TYPCHECKS
+*****************************************************************************/
+
+
+
+/*************** interne Funktion: builtin_isanysubclass *********************
+
+       "uberpr"uft, ob eine Klasse eine Unterklasse einer anderen Klasse ist.
+       Dabei gelten auch Interfaces, die eine Klasse implementiert, als
+       deren Oberklassen. 
+       R"uckgabewert:  1 ... es trifft zu
+                       0 ... es trifft nicht zu
+                       
+*****************************************************************************/                 
+
+static s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+{
+       if (super->flags & ACC_INTERFACE) {
+               u4 index = super->index;
+/*             if (sub->vftbl == NULL) return 0; */
+               if (index >= sub->vftbl->interfacetablelength) return 0;
+               return ( sub->vftbl->interfacevftbl[index] ) ? 1 : 0;
+               }
+       else {
+               while (sub) {
+                       if (sub==super) return 1;
+                       sub = sub->super;
+                       }
+               return 0;
+               }
+}
+
+
+/****************** Funktion: builtin_instanceof *****************************
+
+       "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+       abgeleiteten Klasse) ist, oder ob die Klasse des Objekts ein Interface 
+       implementiert.
+       Return:   1, wenn ja
+                 0, wenn nicht, oder wenn Objekt ein NULL-Zeiger
+                
+*****************************************************************************/
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+       log_text ("builtin_instanceof called");
+#endif
+       
+       if (!obj) return 0;
+       return builtin_isanysubclass (obj->vftbl->class, class);
+}
+
+
+
+/**************** Funktion: builtin_checkcast *******************************
+
+       "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+       abgeleiteten Klasse ist).
+       Unterschied zu builtin_instanceof: Ein NULL-Zeiger ist immer richtig
+       Return:   1, wenn ja, oder wenn Objekt ein NULL-Zeiger 
+              0, wenn nicht
+              
+****************************************************************************/
+
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+       log_text ("builtin_checkcast called");
+#endif
+
+       if (!obj) return 1;
+       if ( builtin_isanysubclass (obj->vftbl->class, class) ) {
+               return 1;
+                               }
+#if DEBUG
+               printf ("#### checkcast failed ");
+               unicode_display (obj->vftbl->class->name);
+               printf (" -> ");
+               unicode_display (class->name);
+               printf ("\n");
+#endif
+               
+       return 0;
+}
+
+
+
+/*********** interne Funktion: builtin_descriptorscompatible ******************
+
+       "uberpr"uft, ob zwei Array-Typdescriptoren compartible sind, d.h.,
+       ob ein Array vom Typ 'desc' gefahrlos einer Variblen vom Typ 'target'
+       zugewiesen werden kann.
+       Return: 1, wenn ja
+               0, wenn nicht
+               
+******************************************************************************/
+
+static s4 builtin_descriptorscompatible
+       (constant_arraydescriptor *desc, constant_arraydescriptor *target)
+{
+       if (desc==target) return 1;
+       if (desc->arraytype != target->arraytype) return 0;
+       switch (target->arraytype) {
+               case ARRAYTYPE_OBJECT: 
+                       return builtin_isanysubclass (desc->objectclass, target->objectclass);
+               case ARRAYTYPE_ARRAY:
+                       return builtin_descriptorscompatible 
+                         (desc->elementdescriptor, target->elementdescriptor);
+               default: return 1;
+               }
+}
+
+
+
+/******************** Funktion: builtin_checkarraycast ***********************
+
+       "uberpr"uft, ob ein gegebenes Objekt tats"achlich von einem 
+       Untertyp des geforderten Arraytyps ist.
+       Dazu muss das Objekt auf jeden Fall ein Array sein. 
+       Bei einfachen Arrays (int,short,double,etc.) muss der Typ genau 
+       "ubereinstimmen.
+       Bei Arrays von Objekten muss der Elementtyp des tats"achlichen Arrays
+       ein Untertyp (oder der selbe Typ) vom geforderten Elementtyp sein.
+       Bei Arrays vom Arrays (die eventuell wieder Arrays von Arrays
+       sein k"onnen) m"ussen die untersten Elementtypen in der entsprechenden
+       Unterklassenrelation stehen.
+
+       Return: 1, wenn Cast in Ordung ist
+                       0, wenn es nicht geht
+       
+       Achtung: ein Cast mit einem NULL-Zeiger geht immer gut.
+                       
+*****************************************************************************/
+
+s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
+{
+       java_arrayheader *a = (java_arrayheader*) o;
+
+       if (!o) return 1;
+       if (o->vftbl->class != class_array) {
+               return 0;
+               }
+               
+       if (a->arraytype != desc->arraytype) {
+               return 0;
+               }
+       
+       switch (a->arraytype) {
+               case ARRAYTYPE_OBJECT: {
+                       java_objectarray *oa = (java_objectarray*) o;
+                       return builtin_isanysubclass (oa->elementtype, desc->objectclass);
+                       }
+               case ARRAYTYPE_ARRAY: {
+                       java_arrayarray *aa = (java_arrayarray*) o;
+                       return builtin_descriptorscompatible
+                          (aa->elementdescriptor, desc->elementdescriptor);
+                       }
+               default:   
+                       return 1;
+               }
+}
+
+
+s4 builtin_arrayinstanceof
+       (java_objectheader *obj, constant_arraydescriptor *desc)
+{
+       if (!obj) return 1;
+       return builtin_checkarraycast (obj, desc);
+}
+
+
+/************************** exception functions *******************************
+
+******************************************************************************/
+
+java_objectheader *builtin_throw_exception (java_objectheader *exceptionptr) {
+       unicode_display (exceptionptr->vftbl->class->name);
+       printf ("\n");
+       fflush (stdout);
+       return exceptionptr;
+}
+
+
+/******************* Funktion: builtin_canstore *******************************
+
+       "uberpr"uft, ob ein Objekt in einem Array gespeichert werden 
+       darf.
+       Return: 1, wenn es geht
+                       0, wenn nicht
+
+******************************************************************************/
+
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
+{
+       if (!o) return 1;
+       
+       switch (a->header.arraytype) {
+       case ARRAYTYPE_OBJECT:
+               if ( ! builtin_checkcast (o, a->elementtype) ) {
+                       return 0;
+                       }
+               return 1;
+               break;
+
+       case ARRAYTYPE_ARRAY:
+               if ( ! builtin_checkarraycast 
+                        (o, ((java_arrayarray*)a)->elementdescriptor) ) {
+                       return 0;
+                       }
+               return 1;
+               break;
+
+       default:
+               panic ("builtin_canstore called with invalid arraytype");
+               return 0;
+       }
+}
+
+
+
+/*****************************************************************************
+                          ARRAYOPERATIONEN
+*****************************************************************************/
+
+
+
+/******************** Funktion: builtin_new **********************************
+
+       Legt ein neues Objekt einer Klasse am Heap an.
+       Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+                       mehr frei ist.
+                       
+*****************************************************************************/
+
+java_objectheader *builtin_new (classinfo *c)
+{
+       java_objectheader *o;
+       
+       o = heap_allocate ( c->instancesize, true, c->finalizer );
+       if (!o) return NULL;
+       
+       memset (o, 0, c->instancesize);
+
+       o -> vftbl = c -> vftbl;
+       return o;
+}
+
+
+
+/******************** Funktion: builtin_anewarray ****************************
+
+       Legt ein Array von Zeigern auf Objekte am Heap an.
+       Parameter: 
+               size ......... Anzahl der Elemente
+               elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
+                              der Elemente
+
+       Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
+
+*****************************************************************************/
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
+{
+       s4 i;
+       java_objectarray *a;
+       
+       a = heap_allocate ( sizeof(java_objectarray) + (size-1) * sizeof(void*), 
+                           true, 0 /* FALSE */ );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_OBJECT;
+       a -> elementtype = elementtype;
+       for (i=0; i<size; i++) a->data[i] = NULL;
+       return a;
+}
+
+
+
+/******************** Funktion: builtin_newarray_array ***********************
+
+       Legt ein Array von Zeigern auf Arrays am Heap an.
+       Paramter: size ......... Anzahl der Elemente
+                 elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
+                                die Element-Arrays.
+
+       Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_arrayarray *builtin_newarray_array 
+        (s4 size, constant_arraydescriptor *elementdesc)
+{
+       s4 i;
+       java_arrayarray *a;
+       
+       a = heap_allocate ( sizeof(java_arrayarray) + (size-1) * sizeof(void*), 
+                           true, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_ARRAY;
+       a -> elementdescriptor = elementdesc;
+       for (i=0; i<size; i++) a->data[i] = NULL;
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_boolean ************************
+
+       Legt ein Array von Bytes am Heap an, das allerdings als Boolean-Array 
+       gekennzeichnet wird (wichtig bei Casts!)
+
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_booleanarray *builtin_newarray_boolean (s4 size)
+{
+       java_booleanarray *a;
+       
+       a = heap_allocate ( sizeof(java_booleanarray) + (size-1) * sizeof(u1), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_BOOLEAN;
+       memset (a->data, 0, sizeof(u1) * size);
+
+       return a;
+}
+
+/******************** Funktion: builtin_newarray_char ************************
+
+       Legt ein Array von 16-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_chararray *builtin_newarray_char (s4 size)
+{
+       java_chararray *a;
+       
+       a = heap_allocate ( sizeof(java_chararray) + (size-1) * sizeof(u2), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_CHAR;
+       memset (a->data, 0, sizeof(u2) * size);
+
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_float ***********************
+
+       Legt ein Array von 32-bit-IEEE-float am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_floatarray *builtin_newarray_float (s4 size)
+{
+       s4 i;
+       java_floatarray *a;
+       
+       a = heap_allocate ( sizeof(java_floatarray) + (size-1) * sizeof(float), 
+                           false, NULL );
+       if (!a) return NULL;
+
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_FLOAT;
+       for (i=0; i<size; i++) a->data[i] = 0.0;
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_double ***********************
+
+       Legt ein Array von 64-bit-IEEE-float am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_doublearray *builtin_newarray_double (s4 size)
+{
+       s4 i;
+       java_doublearray *a;
+       
+       a = heap_allocate ( sizeof(java_doublearray) + (size-1) * sizeof(double), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_DOUBLE;
+       for (i=0; i<size; i++) a->data[i] = 0.0;
+       return a;
+}
+
+
+
+
+/******************** Funktion: builtin_newarray_byte ***********************
+
+       Legt ein Array von 8-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_bytearray *builtin_newarray_byte (s4 size)
+{
+       java_bytearray *a;
+       
+       a = heap_allocate ( sizeof(java_bytearray) + (size-1) * sizeof(s1), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array->vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_BYTE;
+       memset (a->data, 0, sizeof(u1) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_short ***********************
+
+       Legt ein Array von 16-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_shortarray *builtin_newarray_short (s4 size)
+{
+       java_shortarray *a;
+       
+       a = heap_allocate ( sizeof(java_shortarray) + (size-1) * sizeof(s2), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_SHORT;
+       memset (a->data, 0, sizeof(s2) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_int ***********************
+
+       Legt ein Array von 32-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_intarray *builtin_newarray_int (s4 size)
+{
+       java_intarray *a;
+       
+       a = heap_allocate ( sizeof(java_intarray) + (size-1) * sizeof(s4), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_INT;
+       memset (a->data, 0, sizeof(s4) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_long ***********************
+
+       Legt ein Array von 64-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_longarray *builtin_newarray_long (s4 size)
+{
+       java_longarray *a;
+       
+       a = heap_allocate ( sizeof(java_longarray) + (size-1) * sizeof(s8), 
+                           false, NULL );
+       if (!a) return NULL;
+
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_LONG;
+       memset (a->data, 0, sizeof(s8) * size);
+       return a;
+}
+
+
+
+/***************** Funktion: builtin_multianewarray ***************************
+
+       Legt ein mehrdimensionales Array am Heap an.
+       Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
+       "ubergeben. Der Typ es zu erzeugenden Arrays wird als 
+       Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
+
+       Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
+               vorhanden ist.
+
+******************************************************************************/
+
+       /* Hilfsfunktion */
+
+static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
+                       constant_arraydescriptor *desc)
+{
+       u4 size,i;
+       java_arrayarray *a;
+
+       size = dims -> data[thisdim];
+       
+       if (thisdim == (dims->header.size-1)) {
+               /* letzte Dimension schon erreicht */
+               
+               switch (desc -> arraytype) {
+               case ARRAYTYPE_BOOLEAN:  
+                       return (java_arrayheader*) builtin_newarray_boolean (size); 
+               case ARRAYTYPE_CHAR:  
+                       return (java_arrayheader*) builtin_newarray_char (size); 
+               case ARRAYTYPE_FLOAT:  
+                       return (java_arrayheader*) builtin_newarray_float (size); 
+               case ARRAYTYPE_DOUBLE:  
+                       return (java_arrayheader*) builtin_newarray_double (size); 
+               case ARRAYTYPE_BYTE:  
+                       return (java_arrayheader*) builtin_newarray_byte (size); 
+               case ARRAYTYPE_SHORT:  
+                       return (java_arrayheader*) builtin_newarray_short (size); 
+               case ARRAYTYPE_INT:  
+                       return (java_arrayheader*) builtin_newarray_int (size); 
+               case ARRAYTYPE_LONG:  
+                       return (java_arrayheader*) builtin_newarray_long (size); 
+               case ARRAYTYPE_OBJECT:
+                       return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
+               
+               case ARRAYTYPE_ARRAY:
+                       return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
+               
+               default: panic ("Invalid arraytype in multianewarray");
+               }
+               }
+
+       /* wenn letzte Dimension noch nicht erreicht wurde */
+
+       if (desc->arraytype != ARRAYTYPE_ARRAY) 
+               panic ("multianewarray with too many dimensions");
+
+       a = builtin_newarray_array (size, desc->elementdescriptor);
+       if (!a) return NULL;
+       
+       for (i=0; i<size; i++) {
+               java_arrayheader *ea = 
+                 multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
+               if (!ea) return NULL;
+
+               a -> data[i] = ea;
+               }
+               
+       return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+                      constant_arraydescriptor *desc)
+{
+       return multianewarray_part (dims, 0, desc);
+}
+
+
+static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
+                       constant_arraydescriptor *desc)
+{
+       int size, i;
+       java_arrayarray *a;
+
+       size = (int) dims[thisdim];
+       
+       if (thisdim == (n - 1)) {
+               /* letzte Dimension schon erreicht */
+               
+               switch (desc -> arraytype) {
+               case ARRAYTYPE_BOOLEAN:  
+                       return (java_arrayheader*) builtin_newarray_boolean(size); 
+               case ARRAYTYPE_CHAR:  
+                       return (java_arrayheader*) builtin_newarray_char(size); 
+               case ARRAYTYPE_FLOAT:  
+                       return (java_arrayheader*) builtin_newarray_float(size); 
+               case ARRAYTYPE_DOUBLE:  
+                       return (java_arrayheader*) builtin_newarray_double(size); 
+               case ARRAYTYPE_BYTE:  
+                       return (java_arrayheader*) builtin_newarray_byte(size); 
+               case ARRAYTYPE_SHORT:  
+                       return (java_arrayheader*) builtin_newarray_short(size); 
+               case ARRAYTYPE_INT:  
+                       return (java_arrayheader*) builtin_newarray_int(size); 
+               case ARRAYTYPE_LONG:  
+                       return (java_arrayheader*) builtin_newarray_long(size); 
+               case ARRAYTYPE_OBJECT:
+                       return (java_arrayheader*) builtin_anewarray(size,
+                                                  desc->objectclass);
+               case ARRAYTYPE_ARRAY:
+                       return (java_arrayheader*) builtin_newarray_array(size,
+                                                  desc->elementdescriptor);
+               
+               default: panic ("Invalid arraytype in multianewarray");
+               }
+               }
+
+       /* wenn letzte Dimension noch nicht erreicht wurde */
+
+       if (desc->arraytype != ARRAYTYPE_ARRAY) 
+               panic ("multianewarray with too many dimensions");
+
+       a = builtin_newarray_array(size, desc->elementdescriptor);
+       if (!a) return NULL;
+       
+       for (i = 0; i < size; i++) {
+               java_arrayheader *ea = 
+                       nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
+               if (!ea) return NULL;
+
+               a -> data[i] = ea;
+               }
+               
+       return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_nmultianewarray (int size,
+                      constant_arraydescriptor *desc, long *dims)
+{
+       (void) builtin_newarray_int(size); /* for compatibility with -old */
+       return nmultianewarray_part (size, dims, 0, desc);
+}
+
+
+
+
+/************************* Funktion: builtin_aastore *************************
+
+       speichert eine Referenz auf ein Objekt in einem Object-Array oder
+       in einem Array-Array.
+       Dabei wird allerdings vorher "uberpr"uft, ob diese Operation 
+       zul"assig ist.
+
+       Return: 1, wenn alles OK ist
+               0, wenn dieses Objekt nicht in dieses Array gespeichert werden
+                  darf
+
+*****************************************************************************/
+
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
+{
+       if (builtin_canstore(a,o)) {
+               a->data[index] = o;
+               return 1;
+               }
+       return 0;
+}
+
+
+
+
+
+
+/*****************************************************************************
+                      METHODEN-PROTOKOLLIERUNG
+
+       Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
+       kann, wann immer Methoden aufgerufen oder beendet werden.
+       (f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+
+u4 methodindent=0;
+
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+                   methodinfo *method, int *pos, int noindent) {
+
+       if (!noindent)
+               methodindent--;
+       if (verbose || runverbose) {
+               printf("Exception ");
+               unicode_display (exceptionptr->vftbl->class->name);
+               printf(" thrown in ");
+               if (method) {
+                       unicode_display (method->class->name);
+                       printf(".");
+                       unicode_display (method->name);
+                       if (method->flags & ACC_SYNCHRONIZED)
+                               printf("(SYNC)");
+                       else
+                               printf("(NOSYNC)");
+                       printf("(%p) at position %p\n", method->entrypoint, pos);
+                       }
+               else
+                       printf("call_java_method\n");
+               fflush (stdout);
+               }
+       return exceptionptr;
+}
+
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
+                        methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "called: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       sprintf (logtext+strlen(logtext), "(");
+       switch (method->paramcount) {
+               case 6:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3,  a4,  a5);
+                       break;
+               case 5:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3,  a4);
+                       break;
+               case 4:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3);
+                       break;
+               case 3:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0,  a1,  a2);
+                       break;
+               case 2:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx", a0,  a1);
+                       break;
+               case 1:
+                       sprintf(logtext+strlen(logtext), "%lx", a0);
+                       break;
+               }
+       sprintf (logtext+strlen(logtext), ")");
+
+       dolog ();
+       methodindent++;
+}
+
+void builtin_displaymethodstart(methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "called: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       dolog ();
+       methodindent++;
+}
+
+void builtin_displaymethodstop(methodinfo *method, long l, double d)
+{
+       methodindent--;
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "finished: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       switch (method->returntype) {
+               case TYPE_INT:
+               case TYPE_LONG:
+                       sprintf (logtext+strlen(logtext), "->%ld", l);
+                       break;
+               case TYPE_FLOAT:
+               case TYPE_DOUBLE:
+                       sprintf (logtext+strlen(logtext), "->%g", d);
+                       break;
+               case TYPE_ADDRESS:
+                       sprintf (logtext+strlen(logtext), "->%p", (void*) l);
+                       break;
+               }
+       dolog ();
+}
+
+void builtin_displaymethodexception(methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "exception abort: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       dolog ();
+}
+
+
+/****************************************************************************
+             SYNCHRONIZATION FUNCTIONS
+*****************************************************************************/
+
+/*
+ * Lock the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_lock_mutex_for_object (java_objectheader *object)
+{
+    mutexHashEntry *entry;
+    int hashValue;
+
+    assert(object != 0);
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object != 0)
+    {
+               if (entry->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       entry->object = 0;
+                       entry->mutex.holder = 0;
+                       entry->mutex.count = 0;
+                       entry->mutex.muxWaiters = 0;
+               }
+       else
+       {
+           while (entry->next != 0 && entry->object != object)
+               entry = entry->next;
+
+           if (entry->object != object)
+           {
+                       entry->next = firstFreeOverflowEntry;
+                       firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+                       entry = entry->next;
+                       entry->object = 0;
+                       entry->next = 0;
+                       assert(entry->conditionCount == 0);
+           }
+       }
+    }
+    else
+    {
+               entry->mutex.holder = 0;
+               entry->mutex.count = 0;
+               entry->mutex.muxWaiters = 0;
+    }
+
+    if (entry->object == 0)
+        entry->object = object;
+    
+    internal_lock_mutex(&entry->mutex);
+}
+#endif
+
+
+/*
+ * Unlocks the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_unlock_mutex_for_object (java_objectheader *object)
+{
+    int hashValue;
+    mutexHashEntry *entry;
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object == object)
+               internal_unlock_mutex(&entry->mutex);
+    else
+    {
+               while (entry->next != 0 && entry->next->object != object)
+                       entry = entry->next;
+
+               assert(entry->next != 0);
+
+               internal_unlock_mutex(&entry->next->mutex);
+
+               if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       mutexHashEntry *unlinked = entry->next;
+
+                       entry->next = unlinked->next;
+                       unlinked->next = firstFreeOverflowEntry;
+                       firstFreeOverflowEntry = unlinked;
+               }
+    }
+}
+#endif
+
+void
+builtin_monitorenter (java_objectheader *o)
+{
+#ifdef USE_THREADS
+    int hashValue;
+
+       assert(blockInts == 0);
+
+    ++blockInts;
+
+    hashValue = MUTEX_HASH_VALUE(o);
+    if (mutexHashTable[hashValue].object == o
+               && mutexHashTable[hashValue].mutex.holder == currentThread)
+               ++mutexHashTable[hashValue].mutex.count;
+    else
+               internal_lock_mutex_for_object(o);
+
+       --blockInts;
+
+       assert(blockInts == 0);
+#endif
+}
+
+void builtin_monitorexit (java_objectheader *o)
+{
+#ifdef USE_THREADS
+    int hashValue;
+
+       assert(blockInts == 0);
+
+    ++blockInts;
+
+    hashValue = MUTEX_HASH_VALUE(o);
+    if (mutexHashTable[hashValue].object == o)
+    {
+               if (mutexHashTable[hashValue].mutex.count == 1
+                       && mutexHashTable[hashValue].mutex.muxWaiters != 0)
+                       internal_unlock_mutex_for_object(o);
+               else
+                       --mutexHashTable[hashValue].mutex.count;
+    }
+    else
+               internal_unlock_mutex_for_object(o);
+
+       --blockInts;
+
+       assert(blockInts == 0);
+#endif
+}
+
+
+/*****************************************************************************
+                      DIVERSE HILFSFUNKTIONEN
+*****************************************************************************/
+
+
+
+/*********** Funktionen f"ur die Integerdivision *****************************
+       Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
+       division unterst"utzt.
+       Daf"ur gibt es dann diese Hilfsfunktionen
+
+******************************************************************************/
+
+s4 builtin_idiv (s4 a, s4 b) { return a/b; }
+s4 builtin_irem (s4 a, s4 b) { return a%b; }
+
+
+/************** Funktionen f"ur Long-Arithmetik *******************************
+
+       Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
+       werden diese Funktionen gebraucht
+
+******************************************************************************/
+
+
+s8 builtin_ladd (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a+b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lsub (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a-b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lmul (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a*b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_ldiv (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a/b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lrem (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a%b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshl (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return a<<(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshr (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return a>>(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lushr (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return ((u8)a)>>(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_land (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a&b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lor (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a|b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lxor (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a^b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lneg (s8 a) 
+{ 
+#if U8_AVAILABLE
+       return -a;
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s4 builtin_lcmp (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       if (a<b) return -1;
+       if (a>b) return 1;
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+
+
+
+
+/*********** Funktionen f"ur die Floating-Point-Operationen ******************/
+
+float builtin_fadd (float a, float b)
+{
+       if (isnanf(a)) return FLT_NAN;
+       if (isnanf(b)) return FLT_NAN;
+       if (finitef(a)) {
+               if (finitef(b)) return a+b;
+               else return b;
+               }
+       else {
+               if (finitef(b)) return a;
+               else {
+                       if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
+                       else  return FLT_NAN;
+                       }
+               }
+}
+
+float builtin_fsub (float a, float b)
+{
+       return builtin_fadd (a, builtin_fneg(b));
+}
+
+float builtin_fmul (float a, float b)
+{
+       if (isnanf(a)) return FLT_NAN;
+       if (isnanf(b)) return FLT_NAN;
+       if (finitef(a)) {
+               if (finitef(b)) return a*b;
+               else {
+                       if (a==0) return FLT_NAN;
+                            else return copysignf(b, copysignf(1.0, b)*a);
+                       }
+               }
+       else {
+               if (finitef(b)) {
+                       if (b==0) return FLT_NAN;
+                            else return copysignf(a, copysignf(1.0, a)*b);
+                       }
+               else {
+                       return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+                       }
+               }
+}
+
+float builtin_fdiv (float a, float b)
+{
+       if (finitef(a) && finitef(b)) {
+               if (b != 0)
+                       return a / b;
+               else {
+                       if (a > 0)
+                               return FLT_POSINF;
+                       else if (a < 0)
+                               return FLT_NEGINF;
+                       }
+               }
+       return FLT_NAN;
+}
+
+float builtin_frem (float a, float b)
+{
+
+/* return (float) builtin_drem((double) a, (double) b); */
+
+       float f;
+
+       if (finite((double) a) && finite((double) b)) {
+               f = a / b;
+               if (finite((double) f))
+                       return fmodf(a, b);
+               return FLT_NAN;
+               }
+       if (isnan((double) b))
+               return FLT_NAN;
+       if (finite((double) a))
+               return a;
+       return FLT_NAN;
+
+/*     float f;
+
+       if (finitef(a) && finitef(b)) {
+               f = a / b;
+               if (finitef(f))
+                       return a - floorf(f) * b;
+               return FLT_NAN;
+               }
+       if (isnanf(b))
+               return FLT_NAN;
+       if (finitef(a))
+               return a;
+       return FLT_NAN; */
+}
+
+
+float builtin_fneg (float a)
+{
+       if (isnanf(a)) return a;
+       else {
+               if (finitef(a)) return -a;
+                          else return copysignf(a,-copysignf(1.0, a));
+               }
+}
+
+s4 builtin_fcmpl (float a, float b)
+{
+       if (isnanf(a)) return -1;
+       if (isnanf(b)) return -1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0,  a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+s4 builtin_fcmpg (float a, float b)
+{
+       if (isnanf(a)) return 1;
+       if (isnanf(b)) return 1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0, a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+
+
+/*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
+
+double builtin_dadd (double a, double b)
+{
+       if (isnan(a)) return DBL_NAN;
+       if (isnan(b)) return DBL_NAN;
+       if (finite(a)) {
+               if (finite(b)) return a+b;
+               else return b;
+               }
+       else {
+               if (finite(b)) return a;
+               else {
+                       if (copysign(1.0, a)==copysign(1.0, b)) return a;
+                       else  return DBL_NAN;
+                       }
+               }
+}
+
+double builtin_dsub (double a, double b)
+{
+       return builtin_dadd (a, builtin_dneg(b));
+}
+
+double builtin_dmul (double a, double b)
+{
+       if (isnan(a)) return DBL_NAN;
+       if (isnan(b)) return DBL_NAN;
+       if (finite(a)) {
+               if (finite(b)) return a*b;
+               else {
+                       if (a==0) return DBL_NAN;
+                            else return copysign(b, copysign(1.0, b)*a);
+                       }
+               }
+       else {
+               if (finite(b)) {
+                       if (b==0) return DBL_NAN;
+                            else return copysign(a, copysign(1.0, a)*b);
+                       }
+               else {
+                       return copysign(a, copysign(1.0, a)*copysign(1.0, b));
+                       }
+               }
+}
+
+double builtin_ddiv (double a, double b)
+{
+       if (finite(a) && finite(b)) {
+               if (b != 0)
+                       return a / b;
+               else {
+                       if (a > 0)
+                               return DBL_POSINF;
+                       else if (a < 0)
+                               return DBL_NEGINF;
+                       }
+               }
+       return DBL_NAN;
+}
+
+double builtin_drem (double a, double b)
+{
+       double d;
+
+       if (finite(a) && finite(b)) {
+               d = a / b;
+               if (finite(d)) {
+                       if ((d < 1.0) && (d > 0.0))
+                               return a;
+                       return fmod(a, b);
+                       }
+               return DBL_NAN;
+               }
+       if (isnan(b))
+               return DBL_NAN;
+       if (finite(a))
+               return a;
+       return DBL_NAN;
+}
+
+double builtin_dneg (double a)
+{
+       if (isnan(a)) return a;
+       else {
+               if (finite(a)) return -a;
+                         else return copysign(a,-copysign(1.0, a));
+               }
+}
+
+s4 builtin_dcmpl (double a, double b)
+{
+       if (isnan(a)) return -1;
+       if (isnan(b)) return -1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+s4 builtin_dcmpg (double a, double b)
+{
+       if (isnan(a)) return 1;
+       if (isnan(b)) return 1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+
+/*********************** Umwandlungsoperationen ****************************/
+
+s8 builtin_i2l (s4 i)
+{
+#if U8_AVAILABLE
+       return i;
+#else
+       s8 v; v.high = 0; v.low=i; return v;
+#endif
+}
+
+float builtin_i2f (s4 a)
+{
+float f = (float) a;
+return f;
+}
+
+double builtin_i2d (s4 a)
+{
+double d = (double) a;
+return d;
+}
+
+
+s4 builtin_l2i (s8 l)
+{
+#if U8_AVAILABLE
+       return (s4) l;
+#else
+       return l.low;
+#endif
+}
+
+float builtin_l2f (s8 a)
+{
+#if U8_AVAILABLE
+       float f = (float) a;
+       return f;
+#else
+       return 0.0;
+#endif
+}
+
+double builtin_l2d (s8 a)
+{
+#if U8_AVAILABLE
+       double d = (double) a;
+       return d;
+#else
+       return 0.0;
+#endif
+}
+
+
+s4 builtin_f2i(float a) 
+{
+
+return builtin_d2i((double) a);
+
+/*     float f;
+       
+       if (isnanf(a))
+               return 0;
+       if (finitef(a)) {
+               if (a > 2147483647)
+                       return 2147483647;
+               if (a < (-2147483648))
+                       return (-2147483648);
+               return (s4) a;
+               }
+       f = copysignf((float) 1.0, a);
+       if (f > 0)
+               return 2147483647;
+       return (-2147483648); */
+}
+
+
+s8 builtin_f2l (float a)
+{
+
+return builtin_d2l((double) a);
+
+/*     float f;
+       
+       if (finitef(a)) {
+               if (a > 9223372036854775807L)
+                       return 9223372036854775807L;
+               if (a < (-9223372036854775808L))
+                       return (-9223372036854775808L);
+               return (s8) a;
+               }
+       if (isnanf(a))
+               return 0;
+       f = copysignf((float) 1.0, a);
+       if (f > 0)
+               return 9223372036854775807L;
+       return (-9223372036854775808L); */
+}
+
+
+double builtin_f2d (float a)
+{
+       if (finitef(a)) return (double) a;
+       else {
+               if (isnanf(a)) return DBL_NAN;
+               else           return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+               }
+}
+
+
+s4 builtin_d2i (double a) 
+{ 
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 2147483647)
+                       return 2147483647;
+               if (a <= (-2147483648))
+                       return (-2147483648);
+               return (s4) a;
+               }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 2147483647;
+       return (-2147483648);
+}
+
+
+s8 builtin_d2l (double a)
+{
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 9223372036854775807L)
+                       return 9223372036854775807L;
+               if (a <= (-9223372036854775807L-1))
+                       return (-9223372036854775807L-1);
+               return (s8) a;
+               }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 9223372036854775807L;
+       return (-9223372036854775807L-1);
+}
+
+
+float builtin_d2f (double a)
+{
+       if (finite(a)) return (float) a;
+       else {
+               if (isnan(a)) return FLT_NAN;
+               else          return copysignf (FLT_POSINF, (float) copysign(1.0, a));
+               }
+}
+
diff --git a/builtin.h b/builtin.h
new file mode 100644 (file)
index 0000000..b52afb4
--- /dev/null
+++ b/builtin.h
@@ -0,0 +1,125 @@
+/****************************** builtin.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the prototypes for the functions of file builtin.c which has
+       a more detailed description.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************************** Prototypes *************************************/       
+
+typedef struct builtin_descriptor {
+       functionptr bptr;
+       char        *name;
+       } builtin_descriptor;
+
+extern builtin_descriptor builtin_desc[];
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class);
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 new_builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 builtin_arrayinstanceof
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 builtin_checkarraycast
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 new_builtin_checkarraycast
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+
+java_objectheader *builtin_throw_exception (java_objectheader *exception);
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+                   methodinfo *method, int *pos, int noindent);
+
+java_objectheader *builtin_new (classinfo *c);
+
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype);
+java_arrayarray *builtin_newarray_array 
+        (s4 size, constant_arraydescriptor *elementdesc);
+java_booleanarray *builtin_newarray_boolean (s4 size);
+java_chararray *builtin_newarray_char (s4 size);
+java_floatarray *builtin_newarray_float (s4 size);
+java_doublearray *builtin_newarray_double (s4 size);
+java_bytearray *builtin_newarray_byte (s4 size);
+java_shortarray *builtin_newarray_short (s4 size);
+java_intarray *builtin_newarray_int (s4 size);
+java_longarray *builtin_newarray_long (s4 size);
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+                       constant_arraydescriptor *desc);
+java_arrayheader *builtin_nmultianewarray (int size,
+                      constant_arraydescriptor *desc, long *dims);
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o);
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5, methodinfo *method);
+void builtin_displaymethodstart(methodinfo *method);
+void builtin_displaymethodstop(methodinfo *method, long l, double d);
+/* void builtin_displaymethodstop(methodinfo *method); */
+void builtin_displaymethodexception(methodinfo *method);
+
+void builtin_monitorenter (java_objectheader *o);
+void new_builtin_monitorenter (java_objectheader *o);
+void builtin_monitorexit (java_objectheader *o);
+void new_builtin_monitorexit (java_objectheader *o);
+
+s4 builtin_idiv (s4 a, s4 b); 
+s4 new_builtin_idiv (s4 a, s4 b); 
+s4 builtin_irem (s4 a, s4 b);
+s4 new_builtin_irem (s4 a, s4 b);
+
+s8 builtin_ladd (s8 a, s8 b);
+s8 builtin_lsub (s8 a, s8 b);
+s8 builtin_lmul (s8 a, s8 b);
+s8 builtin_ldiv (s8 a, s8 b);
+s8 new_builtin_ldiv (s8 a, s8 b);
+s8 builtin_lrem (s8 a, s8 b);
+s8 new_builtin_lrem (s8 a, s8 b);
+s8 builtin_lshl (s8 a, s4 b);
+s8 builtin_lshr (s8 a, s4 b);
+s8 builtin_lushr (s8 a, s4 b);
+s8 builtin_land (s8 a, s8 b);
+s8 builtin_lor (s8 a, s8 b);
+s8 builtin_lxor (s8 a, s8 b);
+s8 builtin_lneg (s8 a);
+s4 builtin_lcmp (s8 a, s8 b);
+
+float builtin_fadd (float a, float b);
+float builtin_fsub (float a, float b);
+float builtin_fmul (float a, float b);
+float builtin_fdiv (float a, float b);
+float builtin_frem (float a, float b);
+float builtin_fneg (float a);
+s4 builtin_fcmpl (float a, float b);
+s4 builtin_fcmpg (float a, float b);
+
+double builtin_dadd (double a, double b);
+double builtin_dsub (double a, double b);
+double builtin_dmul (double a, double b);
+double builtin_ddiv (double a, double b);
+double builtin_drem (double a, double b);
+double builtin_dneg (double a);
+s4 builtin_dcmpl (double a, double b);
+s4 builtin_dcmpg (double a, double b);
+
+s8       builtin_i2l (s4 i);
+float    builtin_i2f (s4 i);
+double   builtin_i2d (s4 i);
+s4       builtin_l2i (s8 l);
+float    builtin_l2f (s8 l);
+double   builtin_l2d (s8 l);
+s4       builtin_f2i (float a);
+s8       builtin_f2l (float a);
+double   builtin_f2d (float a);
+s4       builtin_d2i (double a);
+s8       builtin_d2l (double a);
+float    builtin_d2f (double a);
+
diff --git a/callargs.h b/callargs.h
new file mode 100644 (file)
index 0000000..5144375
--- /dev/null
@@ -0,0 +1 @@
+#define TRACECALLARGS
diff --git a/comp/block.c b/comp/block.c
new file mode 100644 (file)
index 0000000..813c88c
--- /dev/null
@@ -0,0 +1,405 @@
+/***************************** comp/block.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Basic block handling functions.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/01/18
+
+*******************************************************************************/
+
+
+static u2 creatornum;  /* Fortlaufende Nummerierung f"ur vom Compiler
+                          generierte BasicBlocks (nur zu Debug-Zwecken) */
+
+static subroutineinfo *actual_subroutine;
+static u2 subroutinecounter=0;
+
+
+/********************** Funktion: block_new ***********************************
+
+       erzeugt eine neue 'basicblock'-Struktur und initialisiert alle 
+       Komponenten 
+
+******************************************************************************/
+
+static basicblock *block_new (u2 type, u4 codepos)
+{
+       basicblock *b = DNEW (basicblock);
+       
+       b -> type = type;
+       b -> reached = false;
+       b -> finished = false;
+       b -> subroutine = NULL;
+       b -> jpc = codepos;
+       b -> stack = NULL;
+       list_init (&(b->pcmdlist), OFFSET (pcmd, linkage) );
+       b -> mpc = 0;
+       
+       b -> exproto = NULL;
+       b -> throwpos = 0;
+       return b;
+}
+
+
+
+/******************* Funktion: block_find *************************************
+
+       Sucht den Basicblock, der an einer gew"unschten Stelle im JavaVM-Code
+       anf"angt.
+       Wenn dort kein Block anf"angt  -> Fehler
+       
+******************************************************************************/
+
+static basicblock *block_find (u4 codepos)
+{
+       basicblock *b = blocks[codepos];
+       if (!b) panic ("Accessed JAVA-Command on no block boundary"); 
+       return b;
+}
+
+
+/****************** Funktion: block_isany *************************************
+
+       "uberpr"uft, ob an einer Stelle ein Basicblock anf"angt
+       
+******************************************************************************/
+
+static bool block_isany (u4 codepos)
+{
+       return (blocks[codepos] != NULL);
+}
+
+
+/***************** Funktion: block_reach **************************************
+
+       H"angt einen Basicblock in die Liste der schon erreichten Bl"ocke ein,
+       und setzt seinen Blockeintrittsstack auf den aktuellen Stack und
+       setzt den Unterprogramminfoblock auf das aktuelle Unterprogramminfo
+       
+       Wenn der Block bereits vorher als erreicht markiert war (und er deshalb
+       schon einen definierten Stack hatte), dann wird im derzeit vom 
+       Parser durchlaufenen Block (also dort, von wo dieser Block aus 
+       angesprungen wird) ein entsprechende Codest"uck hinzugef"ugt, der
+       die beiden Stacks aufeinander abstimmt.
+       
+******************************************************************************/
+
+static void block_reach (basicblock *b)
+{
+       if (!b->reached) {
+               list_addlast (&reachedblocks, b);
+               b -> reached = true;
+               b -> subroutine = actual_subroutine;
+               b -> stack = stack_get();
+               }
+       else {
+               if (b->subroutine != actual_subroutine) 
+                  panic ("Try to merge different subroutines");
+               stack_addjoincode (b->stack);
+               }
+}
+
+/*********************** Funktion: subroutine_set *****************************
+
+       setzt den aktuellen Subroutine-Infoblock 
+       
+*******************************************************************************/
+
+static void subroutine_set (subroutineinfo *s)
+{
+       actual_subroutine = s;
+}
+
+
+
+/*********************** Funktion: subroutine_new *****************************
+
+       erzeugt einen neuen Subroutine-Infoblock
+       
+*******************************************************************************/
+
+static subroutineinfo *subroutine_new ()
+{
+       subroutineinfo *s = DNEW (subroutineinfo);
+       s -> returnfinished = false;
+       s -> returnstack = NULL;
+       s -> callers = chain_dnew();
+       s -> counter = subroutinecounter++;
+       return s;
+}
+
+
+
+
+
+
+/********************** Funktion: block_insert ********************************
+
+       Erzeugt einen neuen Block, der an einer gew"unschten JavaVM-Code- Stelle
+       anf"angt.
+       Der Zeiger auf diesen Block wird im (globalen) 'blocks'-Array 
+       abgelegt.
+       
+******************************************************************************/        
+
+static void block_insert (u4 codepos)
+{
+       if (codepos>=jcodelength) {
+               sprintf (logtext,"Basic block border (%d) out of bounds",(int) codepos);
+               error ();
+               }
+
+       if (blocks[codepos]) return;
+
+       blocks[codepos] = block_new (BLOCKTYPE_JAVA, codepos);
+}
+
+
+
+/******************** Funktion: block_createexcreator *************************
+
+       erzeugt einen neuen Basicblock vom Typ EXCREATOR (=Exception Creator)
+       
+******************************************************************************/
+
+static basicblock *block_createexcreator (java_objectheader *exproto, u4 throwpos)
+{
+       basicblock *b;
+
+       b = block_new (BLOCKTYPE_EXCREATOR, creatornum++);
+       
+       b -> reached = true;
+       list_addlast (&reachedblocks, b);
+       b -> subroutine = actual_subroutine;
+       b -> exproto = exproto;
+       b -> throwpos = throwpos;
+       return b;
+}
+
+
+/******************* Funktion: block_createexforwarder ***********************
+
+       erzeugt einen neuen Basicblock vom Typ EXFORWARDER (=Exception Forwarder)
+       
+*****************************************************************************/
+
+static basicblock *block_createexforwarder (varid exvar, u4 throwpos)
+{
+       basicblock *b;
+
+       b = block_new (BLOCKTYPE_EXFORWARDER, creatornum++);
+       
+       b -> reached = true;
+       list_addlast (&reachedblocks, b);
+       b -> subroutine = actual_subroutine;
+       b -> exvar = exvar;
+       b -> throwpos = throwpos;
+       return b;
+}
+
+
+/********************** Funktion: block_genmcode ******************************
+
+       generiert f"ur einen vom Parser fertig abgearbeiteten Block den
+       Maschinencode.
+       Hintereinanderliegende Bl"ocke durch die der Kontrollflu"s ohne
+       Sprungbefehle durchgeht, m"ussen hier auch hintereinander 
+       abgearbeitet werden.
+       
+******************************************************************************/
+
+/* definition of block_genmcode moved to gen.c for inlining by andi          */
+
+
+/************************ Funktion: block_firstscann **************************
+
+       Liest den JavaVM-Code der ganzen Methode durch und erzeugt soviele
+       neue Bl"ocke, wie es verschiedene Sprungziele gibt.
+       
+******************************************************************************/
+
+static void block_firstscann ()
+{
+       u4 p,nextp;
+       int i;
+       u1 opcode;
+       bool blockend;
+
+
+       creatornum=10001;
+
+
+       block_insert (0);
+
+       for (i=0; i<exceptiontablelength; i++) block_insert(extable[i].handlerpc);
+
+       p=0;
+       blockend = false;
+       while (p<jcodelength) {
+               if (blockend) {
+                       block_insert (p);
+                       blockend = false;
+                       }
+
+               opcode = jcode[p];
+               nextp = p + jcommandsize[opcode];
+
+               switch ( opcode ) {
+                       case CMD_IFEQ:
+                       case CMD_IFNULL:
+                       case CMD_IFLT:
+                       case CMD_IFLE:
+                       case CMD_IFNE:
+                       case CMD_IFNONNULL:
+                       case CMD_IFGT:
+                       case CMD_IFGE:
+                       case CMD_IF_ICMPEQ:
+                       case CMD_IF_ICMPNE:
+                       case CMD_IF_ICMPLT:
+                       case CMD_IF_ICMPGT:
+                       case CMD_IF_ICMPLE:
+                       case CMD_IF_ICMPGE:
+                       case CMD_IF_ACMPEQ:
+                       case CMD_IF_ACMPNE:
+                               block_insert ( p + code_get_s2 (p+1) );
+                               break;
+
+                       case CMD_GOTO:
+                               block_insert ( p + code_get_s2 (p+1) );
+                               blockend = true;
+                               break;
+
+                       case CMD_GOTO_W:
+                               block_insert ( p + code_get_s4 (p+1) );
+                               blockend = true;
+                               break;
+                               
+                       case CMD_JSR:
+                               block_insert ( p + code_get_s2 (p+1) );
+                               blockend = true;
+                               break;
+                       
+                       case CMD_JSR_W:
+                               block_insert ( p + code_get_s4 (p+1) );
+                               blockend = true;
+                               break;
+
+                       case CMD_RET:
+                               blockend = true;
+                               break;
+
+                       case CMD_IRETURN:
+                       case CMD_LRETURN:
+                       case CMD_FRETURN:
+                       case CMD_DRETURN:
+                       case CMD_ARETURN:
+                       case CMD_RETURN:
+                               blockend = true;
+                               break;
+
+                       case CMD_ATHROW:
+                               blockend = true;
+                               break;
+                               
+
+                       case CMD_WIDE:
+                               switch (code_get_u1(p+1)) {
+                               case CMD_RET:   nextp = p+4;
+                                               blockend = true;
+                                               break;
+                               case CMD_IINC:  nextp = p+6;
+                                               break;
+                               default:        nextp = p+4;
+                                               break;
+                               }
+                               break;
+                                                       
+                       case CMD_LOOKUPSWITCH:
+                               { u4 num,p2,i;
+                                       p2 = ALIGN ((p+1),4);
+                                       num = code_get_u4 (p2+4);
+                                       nextp = p2 + 8 + 8*num;
+
+                                       block_insert ( p + code_get_s4(p2) );
+                                       for (i=0; i<num; i++) 
+                                               block_insert ( p + code_get_s4(p2+12+8*i) );
+                                       
+                                       blockend = true;
+                               }
+                               break;
+
+                       case CMD_TABLESWITCH:
+                               { u4 num,p2,i;
+                                       p2 = ALIGN ((p+1),4);
+                                       num= code_get_u4(p2+8) - code_get_u4 (p2+4) + 1;
+                                       nextp = p2 + 12 + 4*num;
+
+                                       block_insert ( p + code_get_s4(p2) );
+                                       
+                                       for (i=0; i<num; i++) 
+                                               block_insert ( p + code_get_s4(p2+12+4*i) );
+                                               
+                                       blockend = true;
+                               }       
+                               break;
+
+                       case CMD_LDC1:
+                               i = code_get_u1(p+1);
+                               goto pushconstantitem;
+                       case CMD_LDC2:
+                       case CMD_LDC2W:
+                               i = code_get_u2(p + 1);
+                       pushconstantitem:
+                               if (class_constanttype(class, i) == CONSTANT_String) {
+                                       unicode *s;
+                                       s = class_getconstant(class, i, CONSTANT_String);
+                                       (void) literalstring_new(s);
+                                       }
+                               break;
+                       }
+
+               if (nextp > jcodelength) panic ("Command-sequence crosses code-boundary");
+               p = nextp;
+               }
+       
+       if (!blockend) panic ("Code does not end with branch/return/athrow - stmt");    
+       
+}
+
+
+
+/************* Funktion: block_display (nur zu Debug-Zwecken) ****************/
+
+void block_display (basicblock *b)
+{
+       pcmd *p;
+       
+       if (b->subroutine) {
+               printf ("\n%ld in subroutine: %d", (long int) b->jpc, (int) b->subroutine->counter);
+               }
+       else {
+               printf ("\n%ld:", (long int) b->jpc);
+               }
+
+       switch (b->type) {
+               case BLOCKTYPE_JAVA:        printf ("(JavaVM code)\n"); break;
+               case BLOCKTYPE_EXCREATOR:   printf ("(Exception creator)\n"); break;
+               case BLOCKTYPE_EXFORWARDER: printf ("(Exception forwarder)\n"); break;
+               }
+               
+       printf ("binding of stack:  "); 
+       stack_display (b->stack); printf ("\n");
+       
+       p = list_first (&(b->pcmdlist));
+       while (p) {
+               pcmd_display (p);
+               p = list_next (&(b->pcmdlist), p);
+               }
+}
+
+
diff --git a/comp/defines.c b/comp/defines.c
new file mode 100644 (file)
index 0000000..09987a6
--- /dev/null
@@ -0,0 +1,772 @@
+/******************************** comp/defines.c *******************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       defines all the constants and data structures of the compiler 
+       
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Michael Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+                  
+       Last Change: 1997/09/22
+
+*******************************************************************************/
+
+#include "../sysdep/types.h"
+
+/*********************** resolve typedef-cycles *******************************/
+
+typedef struct stackinfo stackinfo;
+typedef struct basicblock basicblock;
+typedef struct varinfo varinfo;
+typedef struct subroutineinfo subroutineinfo;
+
+
+/***************************** basic block structure **************************/
+
+#define BLOCKTYPE_JAVA        1
+#define BLOCKTYPE_EXCREATOR   2
+#define BLOCKTYPE_EXFORWARDER 3
+
+/* there are three kinds of basic blocks:
+       JAVA  ........ block which contains JavaVM code (normal case)
+       EXCREATOR  ... block which creates an exception and calls the handler
+       EXFORWARDER .. block which does the dispatching to all possible handlers
+*/
+
+struct basicblock {
+       u2  type;           /* block type */
+       bool reached;       /* true, when block has been reached; the field stack
+                              contains the stack valid before entering block */
+       bool finished;      /* true, if 'pcmdlist' is finished */
+       subroutineinfo *subroutine;  /* info about blocks reachable by JSR */
+       listnode linkage;       /* list chaining */
+       u4 jpc;             /* JavaVM program counter at start of block */
+       stackinfo *stack;   /* stack description */
+       list pcmdlist;      /* list of pseudo commands */
+       u4 mpc;             /* program counter within compiled machine code */
+       java_objectheader *exproto;
+                           /* if (type==EXCREATOR) contains pointer to exception
+                              raising object */
+       varinfo *exvar;     /* if (type==EXFORWARDER) contains exception variable */
+       u4 throwpos;        /* if (type!=JAVA) contains position in program where
+                              the exception was raised */
+       };
+
+
+/***************************** subroutine structure ***************************/
+
+struct subroutineinfo {
+       bool returnfinished;     /* true if return allready has been processed */
+
+       stackinfo *returnstack;  /* stack structure at position of return */
+       chain *callers;          /* a list of all callers */
+       u2 counter;
+       };
+
+
+/************************** stack element structure ***************************/
+
+struct stackinfo {
+       stackinfo *prev; /* pointer to next element towards bootom */
+       varinfo *var;    /* pointer to variable which contains this value */
+       };
+
+
+/************************* pseudo variable structure **************************/
+
+struct varinfo {
+       listnode linkage;      /* list chaining */
+
+       u2 type;               /* basic type of variable */
+       u2 number;             /* sequential numbering (used for debugging) */
+
+       bool saved;            /* true if variable sould survive subroutine calls */
+
+       struct reginfo *reg;   /* registerused by variable */
+
+       /* temporary fields used during parsing */
+
+       list copies;           /* list of all variables which are copies */
+       listnode copylink;     /* chaining for copy list */
+       varinfo *original;     /* pointer to original variable (self reference
+                                 is possible) */
+
+       bool globalscope;      /* true if variable is activ in whole subroutine */
+       bool active;           /* true if variable is currently active (parsing
+                                 a block where the variable is valid ) */
+       };
+
+
+typedef varinfo *varid;
+
+#define NOVAR NULL
+
+
+/************************** pseudo command structure **************************/
+
+/* pseudo command tags */
+
+#define TAG_LOADCONST_I  1      /* load integer constant */
+#define TAG_LOADCONST_L  2      /* load long constant    */
+#define TAG_LOADCONST_F  3      /* load float constant   */
+#define TAG_LOADCONST_D  4      /* load double constant  */
+#define TAG_LOADCONST_A  5      /* load address constant */
+#define TAG_MOVE         6
+#define TAG_OP           7
+#define TAG_MEM          8
+#define TAG_BRA          9
+#define TAG_TABLEJUMP   10
+#define TAG_METHOD      11
+#define TAG_DROP        12
+#define TAG_ACTIVATE    13
+
+
+typedef struct pcmd {
+       listnode linkage;           /* list chaining */
+       int tag;                    /* kind of pseudo command */
+       int opcode;                 /* opcode and kind of pseudo command */
+
+       varinfo *dest;              /* optional destination operand */
+       varinfo *source1;           /* 3 optional source operands */
+       varinfo *source2;
+       varinfo *source3;
+
+       union {
+               struct {                /* load integer constant */
+                       s4 value;
+                       } i;
+               struct {                /* load long constant    */
+                       s8 value;
+                       } l;
+               struct {                /* load float constant   */
+                       float value;
+                       } f;
+               struct {                /* load double constant  */
+                       double value;
+                       } d;
+               struct {                /* load address constant */
+                       voidptr value;
+                       } a;
+
+               struct {                /* move */
+                       u2 type;                /* type of value */
+                       } move;
+
+               struct {                /* memory access (load/store) */
+                       int type;               /* access type */
+                       u4  offset;             /* offset relative to base register */
+                       } mem;
+
+       struct {                /* branch */
+                       basicblock *target;     /* branch target */
+                       } bra;
+
+               struct {                /* branch using table */
+                       u4 targetcount;         /* number of entries */
+                       basicblock **targets;   /* branch target */
+                       } tablejump;
+
+               struct {                /* method call */
+                       methodinfo *method;     /* pointer to 'methodinfo'-structure */
+                       functionptr builtin;    /* C function pointer or NULL */
+                       u2 paramnum;            /* number of parameters */
+                       varid *params;          /* table of parameter variables */
+                       varid exceptionvar;     /* exception variable */
+                       } method;
+
+               } u;
+
+       } pcmd;
+
+
+
+
+
+
+/***************** forward references in branch instructions ******************/
+
+typedef struct mcodereference {
+       listnode linkage;       /* list chaining */
+
+       bool incode;            /* true if code address, false if data address */
+       s4 msourcepos;          /* patching position in code/data segment */
+       basicblock *target;     /* target basic block */
+       } mcodereference;
+
+
+
+
+/********** JavaVM operation codes (sortet) and instruction lengths ***********/
+
+u1 jcommandsize[256] = {
+
+#define CMD_NOP                                0
+               1,
+#define CMD_ACONST_NULL                1
+               1,
+#define CMD_ICONST_M1          2
+               1,
+#define CMD_ICONST_0           3
+               1,
+#define CMD_ICONST_1           4
+               1,
+#define CMD_ICONST_2           5
+               1,
+#define CMD_ICONST_3           6
+               1,
+#define CMD_ICONST_4           7
+               1,
+#define CMD_ICONST_5           8
+               1,
+#define CMD_LCONST_0           9
+               1,
+#define CMD_LCONST_1           10
+               1,
+#define CMD_FCONST_0           11
+               1,
+#define CMD_FCONST_1           12
+               1,
+#define CMD_FCONST_2           13
+               1,
+#define CMD_DCONST_0           14
+               1,
+#define CMD_DCONST_1           15
+               1,
+#define CMD_BIPUSH                     16
+               2,
+#define CMD_SIPUSH                     17
+               3,
+#define CMD_LDC1                       18
+               2,
+#define CMD_LDC2                       19
+               3,
+#define CMD_LDC2W                      20
+               3,
+#define CMD_ILOAD                      21
+               2,
+#define CMD_LLOAD                      22
+               2,
+#define CMD_FLOAD                      23
+               2,
+#define CMD_DLOAD                      24
+               2,
+#define CMD_ALOAD                      25
+               2,
+#define CMD_ILOAD_0            26
+               1,
+#define CMD_ILOAD_1            27
+               1,
+#define CMD_ILOAD_2            28
+               1,
+#define CMD_ILOAD_3            29
+               1,
+#define CMD_LLOAD_0            30
+               1,
+#define CMD_LLOAD_1            31
+               1,
+#define CMD_LLOAD_2            32
+               1,
+#define CMD_LLOAD_3            33
+               1,
+#define CMD_FLOAD_0            34
+               1,
+#define CMD_FLOAD_1            35
+               1,
+#define CMD_FLOAD_2            36
+               1,
+#define CMD_FLOAD_3            37
+               1,
+#define CMD_DLOAD_0            38
+               1,
+#define CMD_DLOAD_1            39
+               1,
+#define CMD_DLOAD_2            40
+               1,
+#define CMD_DLOAD_3            41
+               1,
+#define CMD_ALOAD_0            42
+               1,
+#define CMD_ALOAD_1            43
+               1,
+#define CMD_ALOAD_2            44
+               1,
+#define CMD_ALOAD_3            45
+               1,
+#define CMD_IALOAD                     46
+               1,
+#define CMD_LALOAD                     47
+               1,
+#define CMD_FALOAD                     48
+               1,
+#define CMD_DALOAD                     49
+               1,
+#define CMD_AALOAD                     50
+               1,
+#define CMD_BALOAD                     51
+               1,
+#define CMD_CALOAD                     52
+               1,
+#define CMD_SALOAD                     53
+               1,
+#define CMD_ISTORE                     54
+               2,
+#define CMD_LSTORE                     55
+               2,
+#define CMD_FSTORE                     56
+               2,
+#define CMD_DSTORE                     57
+               2,
+#define CMD_ASTORE                     58
+               2,
+#define CMD_ISTORE_0           59
+               1,
+#define CMD_ISTORE_1           60
+               1,
+#define CMD_ISTORE_2           61
+               1,
+#define CMD_ISTORE_3           62
+               1,
+#define CMD_LSTORE_0           63
+               1,
+#define CMD_LSTORE_1           64
+               1,
+#define CMD_LSTORE_2           65
+               1,
+#define CMD_LSTORE_3           66
+               1,
+#define CMD_FSTORE_0           67
+               1,
+#define CMD_FSTORE_1           68
+               1,
+#define CMD_FSTORE_2           69
+               1,
+#define CMD_FSTORE_3           70
+               1,
+#define CMD_DSTORE_0           71
+               1,
+#define CMD_DSTORE_1           72
+               1,
+#define CMD_DSTORE_2           73
+               1,
+#define CMD_DSTORE_3           74
+               1,
+#define CMD_ASTORE_0           75
+               1,
+#define CMD_ASTORE_1           76
+               1,
+#define CMD_ASTORE_2           77
+               1,
+#define CMD_ASTORE_3           78
+               1,
+#define CMD_IASTORE            79
+               1,
+#define CMD_LASTORE            80
+               1,
+#define CMD_FASTORE            81
+               1,
+#define CMD_DASTORE            82
+               1,
+#define CMD_AASTORE            83
+               1,
+#define CMD_BASTORE                84
+               1,
+#define CMD_CASTORE            85
+               1,
+#define CMD_SASTORE            86
+               1,
+#define CMD_POP                    87
+               1,
+#define CMD_POP2                   88
+               1,
+#define CMD_DUP                    89
+               1,
+#define CMD_DUP_X1                 90
+               1,
+#define CMD_DUP_X2                 91
+               1,
+#define CMD_DUP2                   92
+               1,
+#define CMD_DUP2_X1            93
+               1,
+#define CMD_DUP2_X2            94
+               1,
+#define CMD_SWAP                       95
+               1,
+#define CMD_IADD                       96
+               1,
+#define CMD_LADD                       97
+               1,
+#define CMD_FADD                       98
+               1,
+#define CMD_DADD                       99
+               1,
+#define CMD_ISUB                       100
+               1,
+#define CMD_LSUB                       101
+               1,
+#define CMD_FSUB                       102
+               1,
+#define CMD_DSUB                       103
+               1,
+#define CMD_IMUL                       104
+               1,
+#define CMD_LMUL                       105
+               1,
+#define CMD_FMUL                       106
+               1,
+#define CMD_DMUL                       107
+               1,
+#define CMD_IDIV                       108
+               1,
+#define CMD_LDIV                       109
+               1,
+#define CMD_FDIV                       110
+               1,
+#define CMD_DDIV                       111
+               1,
+#define CMD_IREM                       112
+               1,
+#define CMD_LREM                       113
+               1,
+#define CMD_FREM                       114
+               1,
+#define CMD_DREM                       115
+               1,
+#define CMD_INEG                       116
+               1,
+#define CMD_LNEG                       117
+               1,
+#define CMD_FNEG                       118
+               1,
+#define CMD_DNEG                       119
+               1,
+#define CMD_ISHL                       120
+               1,
+#define CMD_LSHL                       121
+               1,
+#define CMD_ISHR                       122
+               1,
+#define CMD_LSHR                       123
+               1,
+#define CMD_IUSHR                      124
+               1,
+#define CMD_LUSHR                      125
+               1,
+#define CMD_IAND                       126
+               1,
+#define CMD_LAND                       127
+               1,
+#define CMD_IOR                        128
+               1,
+#define CMD_LOR                        129
+               1,
+#define CMD_IXOR                       130
+               1,
+#define CMD_LXOR                       131
+               1,
+#define CMD_IINC                       132
+               3,
+#define CMD_I2L                        133
+               1,
+#define CMD_I2F                        134
+               1,
+#define CMD_I2D                        135
+               1,
+#define CMD_L2I                        136
+               1,
+#define CMD_L2F                        137
+               1,
+#define CMD_L2D                        138
+               1,
+#define CMD_F2I                        139
+               1,
+#define CMD_F2L                        140
+               1,
+#define CMD_F2D                    141
+               1,
+#define CMD_D2I                    142
+               1,
+#define CMD_D2L                    143
+               1,
+#define CMD_D2F                    144
+               1,
+#define CMD_INT2BYTE           145
+               1,
+#define CMD_INT2CHAR           146
+               1,
+#define CMD_INT2SHORT          147
+               1,
+#define CMD_LCMP                   148
+               1,
+#define CMD_FCMPL                  149
+               1,
+#define CMD_FCMPG                  150
+               1,
+#define CMD_DCMPL                  151
+               1,
+#define CMD_DCMPG                  152
+               1,
+#define CMD_IFEQ                   153
+               3,
+#define CMD_IFNE                   154
+               3,
+#define CMD_IFLT                   155
+               3,
+#define CMD_IFGE                   156
+               3,
+#define CMD_IFGT                   157
+               3,
+#define CMD_IFLE                   158
+               3,
+#define CMD_IF_ICMPEQ          159
+               3,
+#define CMD_IF_ICMPNE          160
+               3,
+#define CMD_IF_ICMPLT          161
+               3,
+#define CMD_IF_ICMPGE          162
+               3,
+#define CMD_IF_ICMPGT          163
+               3,
+#define CMD_IF_ICMPLE          164
+               3,
+#define CMD_IF_ACMPEQ          165
+               3,
+#define CMD_IF_ACMPNE          166
+               3,
+#define CMD_GOTO                   167
+               3,
+#define CMD_JSR                    168
+               3,
+#define CMD_RET                    169
+               2,
+#define CMD_TABLESWITCH     170
+               0,  /* length must be computed */
+#define CMD_LOOKUPSWITCH    171
+               0,  /* length must be computed */
+#define CMD_IRETURN            172
+               1,
+#define CMD_LRETURN            173
+               1,
+#define CMD_FRETURN            174
+               1,
+#define CMD_DRETURN            175
+               1,
+#define CMD_ARETURN            176
+               1,
+#define CMD_RETURN                 177
+               1,
+#define CMD_GETSTATIC       178
+               3,
+#define CMD_PUTSTATIC       179
+               3,
+#define CMD_GETFIELD        180
+               3,
+#define CMD_PUTFIELD        181
+               3,
+#define CMD_INVOKEVIRTUAL   182
+               3,
+#define CMD_INVOKESPECIAL   183
+               3,
+#define CMD_INVOKESTATIC       184
+               3,
+#define CMD_INVOKEINTERFACE 185
+               5,
+               1, /* unused */
+#define CMD_NEW                    187
+               3,
+#define CMD_NEWARRAY           188
+               2,
+#define CMD_ANEWARRAY          189
+               3,
+#define CMD_ARRAYLENGTH        190
+               1,
+#define CMD_ATHROW             191
+               1,
+#define CMD_CHECKCAST          192
+               3,
+#define CMD_INSTANCEOF         193
+               3,
+#define CMD_MONITORENTER       194
+               1,
+#define CMD_MONITOREXIT                195
+               1,
+#define CMD_WIDE            196
+               0,       /* length must be computed */
+#define CMD_MULTIANEWARRAY     197
+               4,
+#define CMD_IFNULL          198
+               3,
+#define CMD_IFNONNULL      199
+               3,
+#define CMD_GOTO_W          200
+               5,
+#define CMD_JSR_W              201
+               5,
+#define CMD_BREAKPOINT      202
+               1,
+
+               1,1,1,1,1,1,1,1,1,1,            /* unused */
+               1,1,1,1,1,1,1,1,1,1,
+               1,1,1,1,1,1,1,1,1,1,
+               1,1,1,1,1,1,1,1,1,1,
+               1,1,1,1,1,1,1,1,1,1,
+               1,1,1
+       };
+
+#define CMD_TRACEBUILT      253     /* internal opcode */
+#define CMD_IFEQL           254     /* internal opcode */
+#define CMD_IF_UCMPGE       255     /* internal opcode */
+
+#define CMD_LOADCONST_I (CMD_IF_UCMPGE+TAG_LOADCONST_I)   /* internal opcodes */
+#define CMD_LOADCONST_L (CMD_IF_UCMPGE+TAG_LOADCONST_L)
+#define CMD_LOADCONST_F (CMD_IF_UCMPGE+TAG_LOADCONST_F)
+#define CMD_LOADCONST_D (CMD_IF_UCMPGE+TAG_LOADCONST_D)
+#define CMD_LOADCONST_A (CMD_IF_UCMPGE+TAG_LOADCONST_A)
+#define CMD_MOVE        (CMD_IF_UCMPGE+TAG_MOVE)
+
+#define CMD_TABLEJUMP   (CMD_IF_UCMPGE+TAG_TABLEJUMP)
+#define CMD_BUILTIN     (CMD_IF_UCMPGE+TAG_METHOD)
+#define CMD_DROP        (CMD_IF_UCMPGE+TAG_DROP)
+#define CMD_ACTIVATE    (CMD_IF_UCMPGE+TAG_ACTIVATE)
+
+
+/******************* description of JavaVM instructions ***********************/
+
+typedef struct {
+       u1 opcode;
+       u1 type_s1;
+       u1 type_s2;
+       u1 type_d;      
+       functionptr builtin;
+       bool supported;
+       bool isfloat;
+} stdopdescriptor;
+
+stdopdescriptor *stdopdescriptors[256];
+
+stdopdescriptor stdopdescriptortable[] = {
+       { CMD_IADD,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_ISUB,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_IMUL,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_ISHL,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_ISHR,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_IUSHR,  TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_IAND,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_IOR,    TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_IXOR,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { CMD_INEG,   TYPE_INT, TYPE_VOID,TYPE_INT, NULL, true, false },
+
+       { CMD_LADD,   TYPE_LONG, TYPE_LONG, TYPE_LONG, 
+              (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { CMD_LSUB,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { CMD_LMUL,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MULDIV, false },
+       { CMD_LSHL,   TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { CMD_LSHR,   TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { CMD_LUSHR,  TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { CMD_LAND,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_land, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { CMD_LOR,    TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { CMD_LXOR,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lxor, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { CMD_LNEG,   TYPE_LONG, TYPE_VOID, TYPE_LONG,
+              (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { CMD_LCMP,   TYPE_LONG, TYPE_LONG, TYPE_INT,
+              (functionptr) builtin_lcmp, SUPPORT_LONG && SUPPORT_LONG_CMP, false },
+
+       { CMD_FADD,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fadd, SUPPORT_FLOAT, true },
+       { CMD_FSUB,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fsub, SUPPORT_FLOAT, true },
+       { CMD_FMUL,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fmul, SUPPORT_FLOAT, true },
+       { CMD_FDIV,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fdiv, SUPPORT_FLOAT, true },
+       { CMD_FREM,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_frem, SUPPORT_FLOAT, true },
+       { CMD_FNEG,   TYPE_FLOAT, TYPE_VOID,  TYPE_FLOAT, 
+              (functionptr) builtin_fneg, SUPPORT_FLOAT, true },
+       { CMD_FCMPL,  TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,   
+              (functionptr) builtin_fcmpl, SUPPORT_FLOAT, true },
+       { CMD_FCMPG,  TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,   
+              (functionptr) builtin_fcmpg, SUPPORT_FLOAT, true },
+
+       { CMD_DADD,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dadd, SUPPORT_DOUBLE, true },
+       { CMD_DSUB,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dsub, SUPPORT_DOUBLE, true },
+       { CMD_DMUL,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dmul, SUPPORT_DOUBLE, true },
+       { CMD_DDIV,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_ddiv, SUPPORT_DOUBLE, true },
+       { CMD_DREM,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_drem, SUPPORT_DOUBLE, true },
+       { CMD_DNEG,   TYPE_DOUBLE, TYPE_VOID,  TYPE_DOUBLE, 
+              (functionptr) builtin_dneg, SUPPORT_DOUBLE, true },
+       { CMD_DCMPL,  TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, 
+              (functionptr) builtin_dcmpl, SUPPORT_DOUBLE, true },
+       { CMD_DCMPG,  TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, 
+              (functionptr) builtin_dcmpg, SUPPORT_DOUBLE, true },
+
+       { CMD_INT2BYTE, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { CMD_INT2CHAR, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { CMD_INT2SHORT, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { CMD_I2L,    TYPE_INT,  TYPE_VOID, TYPE_LONG,   
+           (functionptr) builtin_i2l, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+       { CMD_I2F,    TYPE_INT,  TYPE_VOID, TYPE_FLOAT,  
+              (functionptr) builtin_i2f, SUPPORT_FLOAT, true },
+       { CMD_I2D,    TYPE_INT,  TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_i2d, SUPPORT_DOUBLE, true },
+       { CMD_L2I,    TYPE_LONG, TYPE_VOID, TYPE_INT,    
+              (functionptr) builtin_l2i, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+       { CMD_L2F,    TYPE_LONG, TYPE_VOID, TYPE_FLOAT,  
+              (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
+       { CMD_L2D,    TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
+       { CMD_F2I,    TYPE_FLOAT, TYPE_VOID, TYPE_INT,   
+              (functionptr) builtin_f2i, SUPPORT_FLOAT, true },
+       { CMD_F2L,    TYPE_FLOAT, TYPE_VOID, TYPE_LONG,   
+              (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+       { CMD_F2D,    TYPE_FLOAT, TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_f2d, SUPPORT_FLOAT && SUPPORT_DOUBLE, true },
+       { CMD_D2I,    TYPE_DOUBLE, TYPE_VOID, TYPE_INT,   
+              (functionptr) builtin_d2i, SUPPORT_DOUBLE, true },
+       { CMD_D2L,    TYPE_DOUBLE, TYPE_VOID, TYPE_LONG,   
+              (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+       { CMD_D2F,    TYPE_DOUBLE, TYPE_VOID, TYPE_FLOAT, 
+              (functionptr) builtin_d2f, SUPPORT_DOUBLE && SUPPORT_FLOAT, true },
+       
+};
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES   0         /* reserved register for OS or code generator */
+#define REG_RET   1         /* return value register */
+#define REG_EXC   2         /* exception value register */
+#define REG_SAV   3         /* (callee) saved register */
+#define REG_TMP   4         /* scratch temporary register (caller saved) */
+#define REG_ARG   5         /* argument register (caller saved) */
+
+#define REG_END   -1        /* last entry in tables */
+#define PARAMMODE_NUMBERED  0 
+#define PARAMMODE_STUFFED   1
+
+/***************************** register info block ****************************/
+
+extern int regdescint[];    /* description of integer registers */
+extern int regdescfloat[];  /* description of floating point registers */
+
+extern int reg_parammode;
+
diff --git a/comp/local.c b/comp/local.c
new file mode 100644 (file)
index 0000000..37098bd
--- /dev/null
@@ -0,0 +1,104 @@
+/**************************** comp/local.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       behandeln der lokalen Java-Variablen
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+       /* es werden f"ur die lokalen Java-Variablen 5 Tabellen angelegt,
+          f"ur jeden m"oglichen Typ eine, weil mehrere Java-Variablen 
+          verschiendenen Typs die selben Slots belegen k"onnen */
+
+varid *locals[5];
+
+
+/*********************** Funktion: local_get **********************************
+
+       erzeugt eine neue Pseudo-Variable f"ur einen JavaVM-Slot und einen
+       gew"unschten Typ, oder eine bereits vorhandene Variable.
+
+******************************************************************************/
+
+static varid local_get (int slot, int type)
+{
+       varid v;
+       int   secondslot;
+       
+       secondslot = ((type==TYPE_DOUBLE) || (type==TYPE_LONG)) ? 1 : 0;
+
+       if (slot+secondslot>=maxlocals) 
+               panic ("Local-variable access out of bounds");
+       v = locals[type][slot];
+
+       if (v==NULL) {
+               v = var_createwithspecialnumber (type, slot);
+               v -> globalscope = true;
+               locals[type][slot] = v;
+               }
+
+       return v;
+}
+
+
+
+
+/************************* Funktion: local_init *******************************
+       
+       legt die 5 Tabellen an, und erzeugt auch gleich die Belegungen
+       f"ur die Methodenparameter.
+
+******************************************************************************/
+
+static void local_init()
+{
+       int t, i, slot;
+       
+       if (TYPE_INT != 0 || TYPE_ADDRESS != 4) 
+         panic ("JAVA-Basictypes have been changed");
+               
+       for (t=TYPE_INT; t<=TYPE_ADDRESS; t++) {
+               locals[t] = DMNEW (varid, maxlocals);
+               for (i=0; i<maxlocals; i++) locals[t][i] = NULL;
+               }
+
+
+       slot =0;
+       for (i=0; i<mparamnum; i++) {
+               t = mparamtypes[i];
+               mparamvars[i] = local_get (slot, t);
+               slot += ((t==TYPE_DOUBLE || t==TYPE_LONG) ? 2 : 1);
+               }
+}
+
+
+/************************ Funktion: local_regalloc ****************************
+
+       f"uhrt die Registerbelegung f"ur die lokalen Java-Variablen durch
+       
+******************************************************************************/
+       
+
+static void local_regalloc ()
+{
+       int   s, t;
+       varid v;
+       
+       for (s=0; s<maxlocals; s++) 
+               for (t=TYPE_INT; t<=TYPE_ADDRESS; t++) {
+                       v = locals[t][s];
+                       if (v) {
+                               if (! isleafmethod)
+                                       var_makesaved (v);
+                               if (v->reg == NULL)
+                                       v->reg = reg_allocate (v->type, v->saved, true);
+                               }
+                       }
+}
+
diff --git a/comp/mcode.c b/comp/mcode.c
new file mode 100644 (file)
index 0000000..ab70734
--- /dev/null
@@ -0,0 +1,325 @@
+/***************************** comp/mcode.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       This file is an include file for "compiler.c" . It contains (mostly)
+       architecture independent functions for writing instructions into the
+       code area and constants into the data area.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Micheal Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/04/13
+
+
+       All functions assume the following code area / data area layout:
+
+       +-----------+
+       |           |
+       | code area | code area grows to higher addresses
+       |           |
+       +-----------+ <-- start of procedure
+       |           |
+       | data area | data area grows to lower addresses
+       |           |
+       +-----------+
+
+       The functions first write into a temporary code/data area allocated by
+       "mcode_init". "mcode_finish" copies the code and data area into permanent
+       memory. All functions writing values into the data area return the offset
+       relative the begin of the code area (start of procedure).       
+
+*******************************************************************************/
+
+#include <sys/mman.h>
+#include <errno.h>
+
+#define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
+
+static u1* mcodebase = NULL;        /* base pointer of code area              */
+static int mcodesize;               /* complete size of code area (bytes)     */
+static int mcodelen;                /* used size of code area (bytes)         */
+
+static u1* dsegtop = NULL;          /* pointer to top (end) of data area      */
+static int dsegsize;                /* complete size of data area (bytes)     */
+static int dseglen;                 /* used size of data area (bytes)         */
+                                    /* data area grows from top to bottom     */
+
+static list mcodereferences;        /* list of branch instruction adresses    */
+                                    /* and of jumptable target addresses      */
+
+static void mcode_init();           /* allocates code and data area           */
+static void mcode_close();          /* releases temporary storage             */
+static void mcode_finish();         /* makes code and data area permanent and */
+                                    /* updates branch references to code/data */
+static void mcode_adds4(s4 code);   /* adds an instruction to code area       */
+
+static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
+static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
+static s4 dseg_addfloat (float value);  /* adds an float to data area         */
+static s4 dseg_adddouble(double value); /* adds an double to data area        */
+
+/*     s4 dseg_addaddress(void* value); */
+static s4 dseg_addtarget(basicblock *target);
+static void mcode_addreference(basicblock *target);
+static void dseg_display();
+
+/* mcode_init allocates and initialises code area, data area and references   */
+
+static void mcode_init()
+{
+       if (!mcodebase) {
+               mcodebase = MNEW (u1, MCODEINITSIZE);
+               mcodesize = MCODEINITSIZE;
+               }
+
+       if (!dsegtop) {
+               dsegtop = MNEW (u1, DSEGINITSIZE);
+               dsegsize = DSEGINITSIZE;
+               dsegtop += dsegsize;
+               }
+
+       mcodelen = 0;
+       dseglen = 0;
+
+       list_init (&mcodereferences, OFFSET(mcodereference, linkage) );
+}
+
+
+/* mcode_close releases temporary code and data area                          */
+
+static void mcode_close()
+{
+       if (mcodebase) {
+               MFREE (mcodebase, u1, mcodesize);
+               mcodebase = NULL;
+               }
+       if (dsegtop) {
+               MFREE (dsegtop - dsegsize, u1, dsegsize);
+               dsegtop = NULL;
+               }
+}
+
+
+/* mcode_adds4_increase doubles code area and adds instruction                */
+
+static void mcode_adds4_increase(s4 code)
+{
+       mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
+       mcodesize *= 2;
+       *((s4 *) (mcodebase + mcodelen - 4)) = code;
+}
+
+
+/* mcode_adds4 checks code area size and adds instruction                     */
+
+static void mcode_adds4(s4 code)
+{
+       s4 *codeptr;
+
+       codeptr = (s4 *) (mcodebase + mcodelen);
+       mcodelen += 4;
+       if (mcodelen <= mcodesize)
+               *codeptr = code;
+       else
+               mcode_adds4_increase(code);
+}
+
+
+/* desg_increase doubles data area                                            */
+
+static void dseg_increase() {
+       u1 *newstorage = MNEW (u1, dsegsize * 2);
+       memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
+       MFREE (dsegtop - dsegsize, u1, dsegsize);
+       dsegtop = newstorage;
+       dsegsize *= 2;
+       dsegtop += dsegsize;
+}
+
+
+static s4 dseg_adds4_increase(s4 value)
+{
+       dseg_increase();
+       *((s4 *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds4(s4 value)
+{
+       s4 *dataptr;
+
+       dseglen += 4;
+       dataptr = (s4 *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adds4_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds8_increase(s8 value)
+{
+       dseg_increase();
+       *((s8 *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds8(s8 value)
+{
+       s8 *dataptr;
+
+       dseglen = ALIGN (dseglen + 8, 8);
+       dataptr = (s8 *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adds8_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_addfloat_increase(float value)
+{
+       dseg_increase();
+       *((float *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_addfloat(float value)
+{
+       float *dataptr;
+
+       dseglen += 4;
+       dataptr = (float *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_addfloat_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adddouble_increase(double value)
+{
+       dseg_increase();
+       *((double *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adddouble(double value)
+{
+       double *dataptr;
+
+       dseglen = ALIGN (dseglen + 8, 8);
+       dataptr = (double *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adddouble_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+#if POINTERSIZE==8
+#define dseg_addaddress(value)      dseg_adds8((s8)(value))
+#else
+#define dseg_addaddress(value)      dseg_adds4((s4)(value))
+#endif
+
+
+static s4 dseg_addtarget(basicblock *target)
+{
+       mcodereference *cr = DNEW(mcodereference);
+
+       dseglen = ALIGN (dseglen + sizeof(void*), sizeof(void*));
+       if (dseglen > dsegsize)
+               dseg_increase();
+
+       cr -> incode = false;
+       cr -> msourcepos = -dseglen;
+       cr -> target = target;
+       
+       list_addlast (&mcodereferences, cr);
+
+       return -dseglen;
+}
+
+
+static void mcode_addreference(basicblock *target)
+{
+       mcodereference *cr = DNEW(mcodereference);
+       
+       cr -> incode = true;
+       cr -> msourcepos = mcodelen;
+       cr -> target = target;
+       
+       list_addlast (&mcodereferences, cr);
+}
+
+
+
+static void mcode_blockstart (basicblock *b)
+{
+       b -> mpc = mcodelen;
+}
+
+
+
+static void gen_resolvebranch(void* mcodepiece, s4 sourcepos, s4 targetpos);
+
+static void mcode_finish()
+{
+       mcodereference *cr;
+
+       count_code_len += mcodelen;
+       count_data_len += dseglen;
+
+       dseglen = ALIGN(dseglen, MAX_ALIGN);
+
+       method->mcodelength = mcodelen + dseglen;
+       method->mcode = CNEW(u1, mcodelen + dseglen);
+
+       memcpy ( method->mcode, dsegtop - dseglen, dseglen);
+       memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+
+       method -> entrypoint = (u1*) (method->mcode + dseglen);
+
+               cr = list_first (&mcodereferences);
+       while (cr != NULL) {
+
+               if (cr->incode) {  /* branch resolving */
+                       gen_resolvebranch ( ((u1*)(method->entrypoint)) + cr->msourcepos, 
+                                   cr->msourcepos,
+                                       cr->target->mpc);
+                       }
+               else {             /* jump table resolving */
+                       void **p;
+                       p = (void**) ( ((u1*)(method->entrypoint)) + cr->msourcepos);
+
+                       *p = ((u1*)(method->entrypoint)) + cr->target->mpc;
+                       }
+
+               cr = list_next (&mcodereferences, cr);
+               }
+
+#ifdef CACHE_FLUSH_BLOCK
+       synchronize_caches(method->mcode, (mcodelen>>2));
+#endif
+       
+}
+
+
+static void dseg_display()
+{
+       int i;
+       printf ("  --- dump of datasegment\n");
+       for (i = dseglen - 4; i >= 0 ; i -= 4) {
+               printf ("%6x: %8x\n", i, (int)(*((s4*)(dsegtop - i))));
+               }
+}
diff --git a/comp/parse.c b/comp/parse.c
new file mode 100644 (file)
index 0000000..9abb4e0
--- /dev/null
@@ -0,0 +1,1662 @@
+/****************************** comp/parse.c ***********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt den Parser f"ur die Bytecode-Darstellung der Methoden
+       
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/17
+
+*******************************************************************************/
+
+
+/* Kurzschreibweise f"ur oft verwendete Funktionen */
+
+#define LOADCONST_I  pcmd_loadconst_i
+#define LOADCONST_L  pcmd_loadconst_l
+#define LOADCONST_F  pcmd_loadconst_f
+#define LOADCONST_D  pcmd_loadconst_d
+#define LOADCONST_A  pcmd_loadconst_a
+#define MOVE         pcmd_move
+#define IINC         pcmd_iinc
+#define OP           pcmd_op
+#define MEM          pcmd_mem
+#define BRA          pcmd_bra
+#define TABLEJUMP    pcmd_tablejump
+#define METHOD       pcmd_method
+
+#define BUILTIN1     pcmd_builtin1
+#define BUILTIN2     pcmd_builtin2
+#define BUILTIN3     pcmd_builtin3
+
+#define DROP         pcmd_drop
+#define ACTIVATE     pcmd_activate
+#define BRA_N_DROP   pcmd_bra_n_drop
+#define MOVE_N_DROP  pcmd_move_n_drop
+
+#define OP1(opcode,s,d)         OP(opcode,s,NOVAR,NOVAR,d)
+#define OP2(opcode,s1,s2,d)     OP(opcode,s1,s2,NOVAR,d)
+#define OP3(opcode,s1,s2,s3,d)  OP(opcode,s1,s2,s3,d)
+
+
+#define EXCREATOR(exclass)      block_createexcreator (exclass, p)
+#define EXFORWARDER(exvar)      block_createexforwarder (exvar, p)
+
+
+
+
+/****************** Funktion: addreturnlog ************************************
+
+       f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
+       ein.
+
+******************************************************************************/
+
+static void addreturnhandling()
+{
+       if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
+               stack_makesaved ();
+#ifdef USE_THREADS
+               if (method->flags & ACC_STATIC) {
+                       varid v = var_create (TYPE_ADDRESS);
+                       LOADCONST_A (class, v);
+                       BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
+                       } 
+               else {
+                       BUILTIN1 ( (functionptr) builtin_monitorexit,
+                                   local_get (0, TYPE_ADDRESS) , NOVAR);
+                       }
+#endif
+               }
+}
+
+
+/*************** Funktion: addreturnexceptionlog *****************************
+
+       f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
+       mit Exception ein.
+
+******************************************************************************/
+
+static void addreturnexceptionhandling()
+{
+
+       if (runverbose) {
+               varid v;
+
+               stack_makesaved ();
+               v = var_create (TYPE_ADDRESS);
+               LOADCONST_A (method, v);
+               BUILTIN1 ( (functionptr) builtin_displaymethodexception, v, NOVAR);
+               }
+               
+       if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
+               stack_makesaved ();
+#ifdef USE_THREADS
+               if (method->flags & ACC_STATIC) {
+                       varid v = var_create (TYPE_ADDRESS);
+                       LOADCONST_A (class, v);
+                       BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
+                       } 
+               else {
+                       BUILTIN1 ( (functionptr) builtin_monitorexit,
+                                   local_get (0, TYPE_ADDRESS) , NOVAR);
+                       }
+#endif
+               }
+}
+
+
+
+/******************************************************************************
+*************** Funktion 'parse' zum Durcharbeiten des Bytecodes **************
+******************************************************************************/
+
+static void parse (basicblock *b)
+{
+       varid v,v1,v2,v3,ve;
+       u4 poolindex;
+       s4 type;
+       u4 p,i;
+       basicblock *target=NULL;
+       bool iswide=false;
+
+       stack_restore (b->stack);
+       subroutine_set (b->subroutine);
+
+
+       switch (b->type) {
+
+               /* Code fuer einen Exception-Forwarder generieren */
+
+
+       case BLOCKTYPE_EXFORWARDER:
+               if (!compileall) {
+                       ACTIVATE (b->exvar);
+                       stack_repush (b->exvar);
+                       stack_makesaved ();
+
+                       for (i=0; i<exceptiontablelength; i++) {
+                               target = block_find (extable[i].handlerpc);
+                               if (   extable[i].startpc <= b->throwpos
+                                   && extable[i].endpc > b->throwpos) {
+
+                                       if (!extable[i].catchtype) goto exceptionfits;
+
+                                       stack_makesaved();
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       v2 = var_create (TYPE_ADDRESS);
+                                       v = var_create (TYPE_INT);
+                                       MOVE (TYPE_ADDRESS, b->exvar, v1);
+                                       LOADCONST_A (extable[i].catchtype, v2);
+                                       BUILTIN2 ((functionptr) builtin_instanceof, v1,v2, v);
+
+                                       block_reach (target);
+                                       BRA_N_DROP (CMD_IFNE, v,NOVAR, NOVAR, target);
+                                       }
+                               }
+                       target = NULL;
+                       }
+               goto exceptionfits;
+
+
+               /* Code fuer einen Exception-Creator generieren */
+       case BLOCKTYPE_EXCREATOR:
+               if (!compileall) {
+                       java_objectheader *o = b->exproto;
+                       LOADCONST_A (o, stack_push(TYPE_ADDRESS) );
+
+                       for (i=0; i<exceptiontablelength; i++) {
+                               target = block_find (extable[i].handlerpc);
+                               if (   extable[i].startpc <= b->throwpos
+                                   && extable[i].endpc > b->throwpos) {
+
+                                       if (!extable[i].catchtype) goto exceptionfits;
+                                       if (builtin_instanceof (o, extable[i].catchtype) ) goto exceptionfits;
+                                       }
+                               }
+                       target = NULL;
+                       }
+
+               /*** Der Sprung zum Exception-Handler (oder Methodenbeendigung) ***/
+
+         exceptionfits:
+               if (!compileall) {
+                       if (target) {
+                               block_reach (target);
+                               BRA (CMD_GOTO, NOVAR,NOVAR,NOVAR, target);
+                               goto cleanup;
+                               }
+
+#ifdef STATISTICS
+       count_pcmd_returnx++;
+#endif
+
+                       switch (mreturntype) {
+                               case TYPE_INT:
+                                       addreturnexceptionhandling();
+
+                                       v1 = var_create (TYPE_INT);
+                                       LOADCONST_I (0, v1);
+                                       BRA_N_DROP (CMD_IRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               case TYPE_LONG:
+                                       addreturnexceptionhandling();
+
+                                       v1 = var_create (TYPE_LONG);
+                                       LOADCONST_I (0, v1);
+                                       BRA_N_DROP (CMD_LRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               case TYPE_FLOAT:
+                                       addreturnexceptionhandling();
+
+                                       v1 = var_create (TYPE_FLOAT);
+                                       LOADCONST_F (0.0, v1);
+                                       BRA_N_DROP (CMD_FRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               case TYPE_DOUBLE:
+                                       addreturnexceptionhandling();
+
+                                       v1 = var_create (TYPE_DOUBLE);
+                                       LOADCONST_D (0.0, v1);
+                                       BRA_N_DROP (CMD_DRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               case TYPE_ADDRESS:
+                                       addreturnexceptionhandling();
+
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (NULL, v1);
+                                       BRA_N_DROP (CMD_ARETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               case TYPE_VOID:
+                                       addreturnexceptionhandling();
+
+                                       BRA (CMD_RETURN, NOVAR,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
+                                       break;
+                               }
+                       }
+               goto cleanup;
+               }
+
+
+               /* Code fuer einen (normalen) JavaVM - Block generieren */
+
+       p = b->jpc;
+
+
+       
+       if ( p==0) {
+               /* Method call protocolling */
+
+               if (runverbose) {
+                       stack_makesaved();
+                       pcmd_trace (method);
+                       }
+
+               /* Synchronization */
+               if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+                       stack_makesaved();
+#ifdef USE_THREADS
+                       if (method->flags & ACC_STATIC) {
+                               varid v = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (class, v);
+                               BUILTIN1 ( (functionptr) builtin_monitorenter, v, NOVAR);
+                       } 
+                       else {
+                               BUILTIN1 ( (functionptr) builtin_monitorenter,
+                                           local_get (0, TYPE_ADDRESS), NOVAR );
+                               }
+#endif
+                       }                       
+               }
+
+       for (;;) {
+               u1 opcode;
+               u4 nextp;
+
+               opcode = code_get_u1 (p);
+               nextp = p + jcommandsize[opcode];
+
+
+               count_javainstr++;
+
+
+               if (showstack) {
+                       printf ("PC: %3d  OPCODE: %3d   Stack: ",(int) p, (int) opcode);
+                       stack_display (stack_get());
+                       printf ("\n");
+                       }
+
+
+               switch (opcode) {
+
+
+                       /*** Pushing constants onto the stack ***/
+
+                       case CMD_BIPUSH:
+                               LOADCONST_I (code_get_s1 (p+1), stack_push (TYPE_INT) );
+                               break;
+
+                       case CMD_SIPUSH:
+                               LOADCONST_I (code_get_s2 (p+1), stack_push (TYPE_INT) );
+                               break;
+
+                       case CMD_LDC1:  poolindex = code_get_u1 (p+1);
+                                       goto pushconstantitem;
+                       case CMD_LDC2:
+                       case CMD_LDC2W: poolindex = code_get_u2 (p+1);
+                       pushconstantitem:
+                               switch (class_constanttype(class, poolindex)) {
+                                       case CONSTANT_Integer:
+                                               { constant_integer *c;
+                                               c = class_getconstant (class, poolindex, CONSTANT_Integer);
+                                               LOADCONST_I (c->value, stack_push(TYPE_INT) );
+                                               }
+                                               break;
+                                       case CONSTANT_Long:
+                                               { constant_long *c;
+                                               c = class_getconstant (class, poolindex, CONSTANT_Long);
+                                               LOADCONST_L (c->value, stack_push(TYPE_LONG) );
+                                               }
+                                               break;
+                                       case CONSTANT_Float:
+                                               { constant_float *c;
+                                               c = class_getconstant (class, poolindex, CONSTANT_Float);
+                                               LOADCONST_F (c->value, stack_push(TYPE_FLOAT) );
+                                               }
+                                               break;
+                                       case CONSTANT_Double:
+                                               { constant_double *c;
+                                               c = class_getconstant (class, poolindex, CONSTANT_Double);
+                                               LOADCONST_D (c->value, stack_push(TYPE_DOUBLE) );
+                                               }
+                                               break;
+
+                                       case CONSTANT_String:
+                                               { unicode *s;
+
+                                               s = class_getconstant (class, poolindex, CONSTANT_String);
+
+                                               LOADCONST_A ( literalstring_new (s),
+                                                             stack_push(TYPE_ADDRESS) );
+                                               }
+                                               break;
+
+                                       default: panic ("Invalid constant type to push");
+                                       }
+                               break;
+
+
+                       case CMD_ACONST_NULL:
+                               LOADCONST_A (0,  stack_push (TYPE_ADDRESS) );
+                               break;
+
+                       case CMD_ICONST_M1:
+                       case CMD_ICONST_0:
+                       case CMD_ICONST_1:
+                       case CMD_ICONST_2:
+                       case CMD_ICONST_3:
+                       case CMD_ICONST_4:
+                       case CMD_ICONST_5:
+                               LOADCONST_I (opcode - CMD_ICONST_0, stack_push (TYPE_INT) );
+                               break;
+
+                       case CMD_LCONST_0:
+                       case CMD_LCONST_1:
+#if U8_AVAILABLE
+                               LOADCONST_L (opcode - CMD_LCONST_0, stack_push (TYPE_LONG) );
+#else
+                               { u8 v;
+                  v.low = opcode - CMD_LCONST_0;
+                                 v.high = 0;
+                                 LOADCONST_L (v, stack_push(TYPE_LONG) );
+                               }
+#endif
+                               break;
+
+                       case CMD_FCONST_0:
+                       case CMD_FCONST_1:
+                       case CMD_FCONST_2:
+                               LOADCONST_F (opcode - CMD_FCONST_0, stack_push (TYPE_FLOAT) );
+                               break;
+
+                       case CMD_DCONST_0:
+                       case CMD_DCONST_1:
+                               LOADCONST_D (opcode - CMD_DCONST_0, stack_push (TYPE_DOUBLE) );
+                               break;
+
+
+                       /*** Loading variables onto the Stack ***/
+
+                       case CMD_ILOAD:
+                               if (!iswide) {
+                                       MOVE ( TYPE_INT,
+                                              local_get (code_get_u1 (p+1), TYPE_INT),
+                                              stack_push (TYPE_INT) );
+                                       }
+                               else {
+                                       MOVE ( TYPE_INT,
+                                              local_get (code_get_u2 (p+1), TYPE_INT),
+                                              stack_push (TYPE_INT) );
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               break;
+
+                       case CMD_ILOAD_0:
+                       case CMD_ILOAD_1:
+                       case CMD_ILOAD_2:
+                       case CMD_ILOAD_3:
+                               MOVE ( TYPE_INT,
+                                      local_get (opcode - CMD_ILOAD_0, TYPE_INT),
+                                      stack_push (TYPE_INT) );
+                               break;
+
+                       case CMD_LLOAD:
+                               if (!iswide) {
+                                       MOVE ( TYPE_LONG,
+                                              local_get (code_get_u1 (p+1), TYPE_LONG),
+                                              stack_push (TYPE_LONG) );
+                                       }
+                               else {
+                                       MOVE ( TYPE_LONG,
+                                              local_get (code_get_u2 (p+1), TYPE_LONG),
+                                              stack_push (TYPE_LONG) );
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               break;
+
+                       case CMD_LLOAD_0:
+                       case CMD_LLOAD_1:
+                       case CMD_LLOAD_2:
+                       case CMD_LLOAD_3:
+                               MOVE ( TYPE_LONG,
+                                      local_get (opcode - CMD_LLOAD_0, TYPE_LONG),
+                                      stack_push (TYPE_LONG) );
+                               break;
+
+                       case CMD_FLOAD:
+                               if (!iswide) {
+                                       MOVE ( TYPE_FLOAT,
+                                              local_get (code_get_u1 (p+1), TYPE_FLOAT),
+                                              stack_push (TYPE_FLOAT) );
+                                       }
+                               else {
+                                       MOVE ( TYPE_FLOAT,
+                                              local_get (code_get_u2 (p+1), TYPE_FLOAT),
+                                              stack_push (TYPE_FLOAT) );
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               break;
+
+                       case CMD_FLOAD_0:
+                       case CMD_FLOAD_1:
+                       case CMD_FLOAD_2:
+                       case CMD_FLOAD_3:
+                               MOVE ( TYPE_FLOAT,
+                                      local_get (opcode - CMD_FLOAD_0, TYPE_FLOAT),
+                                      stack_push (TYPE_FLOAT) );
+                               break;
+
+                       case CMD_DLOAD:
+                               if (!iswide) {
+                                       MOVE ( TYPE_DOUBLE,
+                                              local_get (code_get_u1 (p+1), TYPE_DOUBLE),
+                                              stack_push (TYPE_DOUBLE) );
+                                       }
+                               else {
+                                       MOVE ( TYPE_DOUBLE,
+                                              local_get (code_get_u2 (p+1), TYPE_DOUBLE),
+                                              stack_push (TYPE_DOUBLE) );
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               break;
+
+                       case CMD_DLOAD_0:
+                       case CMD_DLOAD_1:
+                       case CMD_DLOAD_2:
+                       case CMD_DLOAD_3:
+                               MOVE ( TYPE_DOUBLE,
+                                      local_get (opcode - CMD_DLOAD_0, TYPE_DOUBLE),
+                                      stack_push (TYPE_DOUBLE) );
+                               break;
+
+                       case CMD_ALOAD:
+                               if (!iswide) {
+                                       MOVE ( TYPE_ADDRESS,
+                                              local_get (code_get_u1 (p+1), TYPE_ADDRESS),
+                                              stack_push (TYPE_ADDRESS) );
+                                       }
+                               else {
+                                       MOVE ( TYPE_ADDRESS,
+                                              local_get (code_get_u2 (p+1), TYPE_ADDRESS),
+                                              stack_push (TYPE_ADDRESS) );
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               break;
+
+                       case CMD_ALOAD_0:
+                       case CMD_ALOAD_1:
+                       case CMD_ALOAD_2:
+                       case CMD_ALOAD_3:
+                               MOVE ( TYPE_ADDRESS,
+                                      local_get (opcode - CMD_ALOAD_0, TYPE_ADDRESS),
+                                      stack_push (TYPE_ADDRESS) );
+                               break;
+
+
+                       /*** Storing Stack Values into Local Variables ***/
+
+                       case CMD_ISTORE:
+                               v = stack_pop (TYPE_INT);
+                               if (!iswide) {
+                                       MOVE_N_DROP (TYPE_INT, v,
+                                           local_get (code_get_u1 (p+1), TYPE_INT) );
+                                       }
+                               else {
+                                       MOVE_N_DROP (TYPE_INT, v,
+                                           local_get (code_get_u2 (p+1), TYPE_INT) );
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               break;
+
+                       case CMD_ISTORE_0:
+                       case CMD_ISTORE_1:
+                       case CMD_ISTORE_2:
+                       case CMD_ISTORE_3:
+                               v = stack_pop (TYPE_INT);
+                               MOVE_N_DROP (TYPE_INT,
+                                     v, local_get (opcode - CMD_ISTORE_0, TYPE_INT) );
+                               break;
+
+                       case CMD_LSTORE:
+                               v = stack_pop (TYPE_LONG);
+                               if (!iswide) {
+                                       MOVE_N_DROP (TYPE_LONG, v,
+                                           local_get (code_get_u1 (p+1), TYPE_LONG) );
+                                       }
+                               else {
+                                       MOVE_N_DROP (TYPE_LONG, v,
+                                           local_get (code_get_u2 (p+1), TYPE_LONG) );
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               break;
+
+                       case CMD_LSTORE_0:
+                       case CMD_LSTORE_1:
+                       case CMD_LSTORE_2:
+                       case CMD_LSTORE_3:
+                               v = stack_pop (TYPE_LONG);
+                               MOVE_N_DROP (TYPE_LONG,
+                                     v, local_get (opcode - CMD_LSTORE_0, TYPE_LONG) );
+                               break;
+
+                       case CMD_FSTORE:
+                               v = stack_pop (TYPE_FLOAT);
+                               if (!iswide) {
+                                       MOVE_N_DROP (TYPE_FLOAT, v,
+                                           local_get (code_get_u1 (p+1), TYPE_FLOAT) );
+                                       }
+                               else {
+                                       MOVE_N_DROP (TYPE_FLOAT, v,
+                                           local_get (code_get_u2 (p+1), TYPE_FLOAT) );
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               break;
+
+                       case CMD_FSTORE_0:
+                       case CMD_FSTORE_1:
+                       case CMD_FSTORE_2:
+                       case CMD_FSTORE_3:
+                               v = stack_pop (TYPE_FLOAT);
+                               MOVE_N_DROP (TYPE_FLOAT,
+                                     v, local_get (opcode - CMD_FSTORE_0, TYPE_FLOAT) );
+                               break;
+
+                       case CMD_DSTORE:
+                               v = stack_pop (TYPE_DOUBLE);
+                               if (!iswide) {
+                                       MOVE_N_DROP (TYPE_DOUBLE, v,
+                                           local_get (code_get_u1 (p+1), TYPE_DOUBLE) );
+                                       }
+                               else {
+                                       MOVE_N_DROP (TYPE_DOUBLE, v,
+                                           local_get (code_get_u2 (p+1), TYPE_DOUBLE) );
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               break;
+
+                       case CMD_DSTORE_0:
+                       case CMD_DSTORE_1:
+                       case CMD_DSTORE_2:
+                       case CMD_DSTORE_3:
+                               v = stack_pop (TYPE_DOUBLE);
+                               MOVE_N_DROP (TYPE_DOUBLE,
+                                     v, local_get (opcode - CMD_DSTORE_0, TYPE_DOUBLE) );
+                               break;
+
+                       case CMD_ASTORE:
+                               v = stack_pop (TYPE_ADDRESS);
+                               if (!iswide) {
+                                       MOVE_N_DROP (TYPE_ADDRESS, v,
+                                           local_get (code_get_u1 (p+1), TYPE_ADDRESS) );
+                                       }
+                               else {
+                                       MOVE_N_DROP (TYPE_ADDRESS, v,
+                                           local_get (code_get_u2 (p+1), TYPE_ADDRESS) );
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               break;
+
+                       case CMD_ASTORE_0:
+                       case CMD_ASTORE_1:
+                       case CMD_ASTORE_2:
+                       case CMD_ASTORE_3:
+                               v = stack_pop (TYPE_ADDRESS);
+                               MOVE_N_DROP (TYPE_ADDRESS,
+                                     v, local_get (opcode - CMD_ASTORE_0, TYPE_ADDRESS) );
+                               break;
+
+
+                       case CMD_IINC:
+                               if (!iswide) {
+                                       v1 = local_get (code_get_u1 (p+1), TYPE_INT);
+                                       IINC (code_get_s1 (p+2), v1 );
+                                       DROP (v1);
+                                       }
+                               else {
+                                       v1 = local_get (code_get_u2 (p+1), TYPE_INT);
+                                       IINC (code_get_s2 (p+3), v1 );
+                                       DROP (v1);
+                                       iswide = false;
+                                       nextp = p+5;
+                                       }
+                               break;
+
+
+                       /*** Wider index for Loading, Storing and Incrementing ***/
+
+                       case CMD_WIDE:
+                               iswide=true;
+                               nextp = p+1;
+                               break;
+
+
+                       /******************** Managing Arrays **************************/
+
+                       case CMD_NEWARRAY:
+                               v1 = stack_pop (TYPE_INT);
+                               BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+                               stack_makesaved ();
+                               v = stack_push (TYPE_ADDRESS);
+                               switch ( code_get_s1 (p+1) ) {
+                               case 4: BUILTIN1 ((functionptr) builtin_newarray_boolean, v1, v);
+                                           break;
+                               case 5: BUILTIN1 ((functionptr) builtin_newarray_char, v1, v);
+                                           break;
+                               case 6: BUILTIN1 ((functionptr) builtin_newarray_float, v1, v);
+                                           break;
+                               case 7: BUILTIN1 ((functionptr) builtin_newarray_double, v1, v);
+                                           break;
+                               case 8: BUILTIN1 ((functionptr) builtin_newarray_byte, v1, v);
+                                           break;
+                               case 9: BUILTIN1 ((functionptr) builtin_newarray_short, v1, v);
+                                           break;
+                               case 10: BUILTIN1 ((functionptr) builtin_newarray_int, v1, v);
+                                           break;
+                               case 11: BUILTIN1 ((functionptr) builtin_newarray_long, v1, v);
+                                           break;
+                               default: panic ("Invalid array-type to create");
+                               }
+
+                               BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+                               break;
+
+                       case CMD_ANEWARRAY:
+                               poolindex = code_get_u2(p+1);
+                               if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+                                       /* anewarray mit Array-Typ! */
+                                       constant_arraydescriptor *desc =
+                                         class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+                                       v1 = stack_pop (TYPE_INT);
+                                       BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+                                       v2 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (desc, v2);
+
+                                       stack_makesaved ();
+                                       v = stack_push (TYPE_ADDRESS);
+                                       BUILTIN2 ((functionptr) builtin_newarray_array, v1,v2, v);
+                                       BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+                                       }       
+                               else {
+                                       classinfo *c = class_getconstant (class, poolindex, CONSTANT_Class);
+
+                                       v1 = stack_pop (TYPE_INT);
+                                       BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+                                       v2 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (c, v2);
+
+                                       stack_makesaved ();
+                                       v = stack_push (TYPE_ADDRESS);
+                                       BUILTIN2 ((functionptr) builtin_anewarray, v1,v2, v);
+                                       BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+                                       }
+
+                               break;
+
+
+                       case CMD_MULTIANEWARRAY:
+                               { constant_arraydescriptor *desc =
+                                   class_getconstant (class, code_get_u2(p+1), CONSTANT_Arraydescriptor);
+                                 int i, n = code_get_u1 (p+3);
+                                 varid dims =      var_create (TYPE_ADDRESS);  /* array for dimensions */
+                                 varid dimsdim =   var_create (TYPE_INT);      /* groesse des arrays */
+
+                               stack_makesaved ();
+                               LOADCONST_I (n, dimsdim);
+                               BUILTIN1 ((functionptr) builtin_newarray_int, dimsdim, dims);
+                               BRA (CMD_IFNULL, dims,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+                               for (i=0; i<n; i++) {
+                                       varid dimn = stack_pop (TYPE_INT);
+                                       BRA (CMD_IFLT, dimn,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
+
+                                       LOADCONST_I ((n-i)-1, dimsdim);
+                                       OP3 (CMD_IASTORE, dims, dimsdim, dimn, NOVAR);
+                                       DROP (dimsdim);
+                                       DROP (dimn);
+                                       }
+
+                               v = stack_push (TYPE_ADDRESS);
+
+                               v1 = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (desc, v1);
+
+                               BUILTIN2 ((functionptr) builtin_multianewarray, dims, v1, v);
+                               BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+                               }
+                               break;
+
+
+                       case CMD_ARRAYLENGTH:
+                               v = stack_pop (TYPE_ADDRESS);
+                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                       BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
+                                       }
+                               OP1 (opcode, v, stack_push (TYPE_INT) );
+                               DROP (v);
+                               break;
+
+                       case CMD_AALOAD:
+                               type = TYPE_ADDRESS; goto do_aXload;
+                       case CMD_LALOAD:
+                               type = TYPE_LONG; goto do_aXload;
+                       case CMD_FALOAD:
+                               type = TYPE_FLOAT;  goto do_aXload;
+                       case CMD_DALOAD:
+                               type = TYPE_DOUBLE; goto do_aXload;
+                       case CMD_IALOAD:
+                       case CMD_BALOAD:
+                       case CMD_CALOAD:
+                       case CMD_SALOAD:
+                               type = TYPE_INT; goto do_aXload;
+                         do_aXload:
+                               v2 = stack_pop (TYPE_INT);
+                               v1 = stack_pop (TYPE_ADDRESS);
+                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                       BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+                                       }
+                               if (checkbounds) {
+#ifdef STATISTICS
+                                       count_check_bound++;
+#endif
+                                       v = var_create (TYPE_INT);
+                                       OP1 (CMD_ARRAYLENGTH, v1, v);
+                                       BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
+                                       DROP (v);
+                                       }
+                               OP2 (opcode, v1,v2, stack_push (type) );
+                               DROP (v1);
+                               DROP (v2);
+                break;
+
+                       case CMD_AASTORE:
+                               type = TYPE_ADDRESS; goto do_aXstore;
+                       case CMD_LASTORE:
+                               type = TYPE_LONG; goto do_aXstore;
+                       case CMD_FASTORE:
+                               type = TYPE_FLOAT; goto do_aXstore;
+                       case CMD_DASTORE:
+                               type = TYPE_DOUBLE; goto do_aXstore;
+                       case CMD_IASTORE:
+                       case CMD_BASTORE:
+                       case CMD_CASTORE:
+                       case CMD_SASTORE:
+                               type = TYPE_INT; goto do_aXstore;
+                         do_aXstore:
+                               v3 = stack_pop (type);
+                               v2 = stack_pop (TYPE_INT);
+                               v1 = stack_pop (TYPE_ADDRESS);
+                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                       BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+                                       }
+                               if (checkbounds) {
+#ifdef STATISTICS
+                                       count_check_bound++;
+#endif
+                                       v = var_create (TYPE_INT);
+                                       OP1 (CMD_ARRAYLENGTH, v1, v);
+                                       BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
+                                       DROP (v);
+                                       }
+
+                               if (opcode!=CMD_AASTORE) {
+                                       OP3 (opcode, v1,v2,v3, NOVAR);
+                                       DROP (v1);
+                                       DROP (v2);
+                                       DROP (v3);
+                               } else {
+                                       stack_makesaved ();
+
+                                       v = var_create (TYPE_INT);
+                                       BUILTIN3 ((functionptr) builtin_aastore, v1,v2,v3, v);
+                                       BRA (CMD_IFEQ, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArrayStoreException) );
+                                       DROP (v);
+                                       }
+
+                               break;
+
+
+
+                       /******************* Stack instructions **************************/
+
+                       case CMD_NOP:
+                               break;
+
+                       case CMD_POP:
+                               v1 = stack_popany (1);
+                               DROP (v1);
+                               break;
+
+                       case CMD_POP2:
+                               { int varcount, i;
+                                 varid vararray[2];
+
+                               varcount = stack_popmany (vararray, 2);
+                               for (i=0; i<varcount; i++) DROP(vararray[i]);
+                               }
+                               break;
+
+                       case CMD_DUP:
+                               v1 = stack_popany(1);
+                               stack_repush (v1);
+                               v = stack_push ( var_type (v1) );
+                               MOVE (var_type(v1), v1,v);
+                               break;
+
+                       case CMD_DUP2:
+                               { int varcount, i;
+                                 varid vararray[2];
+
+                               varcount = stack_popmany (vararray, 2);
+                               stack_repushmany (varcount, vararray);
+                               for (i=0; i<varcount; i++) {
+                                       v = stack_push ( var_type(vararray[varcount-1-i]) );
+                                       MOVE ( var_type(v), vararray[varcount-1-i], v);
+                                       }
+                               }
+                               break;
+
+                       case CMD_DUP_X1:
+                               v1 = stack_popany(1);
+                               v2 = stack_popany(1);
+
+                               stack_repush (v1);
+                               stack_repush (v2);
+                               v = stack_push ( var_type (v1) );
+                               MOVE (var_type(v1), v1,v);
+                               break;
+
+                       case CMD_DUP2_X1:
+                               { int varcount, i;
+                                 varid vararray[2];
+
+                               varcount = stack_popmany (vararray, 2);
+                               v3 = stack_popany (1);
+                               stack_repushmany (varcount, vararray);
+                               stack_repush (v3);
+                               for (i=0; i<varcount; i++) {
+                                       v = stack_push ( var_type(vararray[varcount-1-i]) );
+                                       MOVE ( var_type(v), vararray[varcount-1-i], v);
+                                       }
+                               }
+                               break;
+
+                       case CMD_DUP_X2:
+                               { int varcount;
+                                 varid vararray[2];
+
+                               v1 = stack_popany(1);
+                               varcount = stack_popmany (vararray, 2);
+                               stack_repush (v1);
+                               stack_repushmany (varcount, vararray);
+                               MOVE (var_type(v1), v1, stack_push(var_type(v1)) );
+                               }
+                               break;
+
+                       case CMD_DUP2_X2:
+                               { int varcount1, varcount2, i;
+                                 varid vararray1[2],vararray2[2];
+
+                               varcount1 = stack_popmany (vararray1, 2);
+                               varcount2 = stack_popmany (vararray2, 2);
+                               stack_repushmany (varcount2, vararray2);
+                               stack_repushmany (varcount1, vararray1);
+                               for (i=0; i<varcount1; i++) {
+                                       v = stack_push ( var_type(vararray1[varcount1-1-i]) );
+                                       MOVE ( var_type(v), vararray1[varcount1-1-i], v);
+                                       }
+                               }
+                               break;
+
+            case CMD_SWAP:
+                               v1 = stack_popany (1);
+                               v2 = stack_popany (1);
+                               stack_repush (v1);
+                               stack_repush (v2);
+
+                           break;
+
+
+                       /*** Arithmetic & logical instructions ***/
+
+                       case CMD_IDIV:
+                       case CMD_IREM:
+                               v2 = stack_pop (TYPE_INT);
+                               v1 = stack_pop (TYPE_INT);
+                               BRA (CMD_IFEQ, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
+
+                               if (SUPPORT_DIVISION) {
+                                       OP2 (opcode, v1,v2, stack_push(TYPE_INT));
+                                       DROP (v1);
+                                       DROP (v2);
+                                       }
+                               else {
+                                       stack_makesaved ();
+                                       BUILTIN2 (
+                                          (opcode == CMD_IDIV) ? 
+                                               ((functionptr) builtin_idiv) 
+                                             : ((functionptr) builtin_irem) 
+                                         ,v1,v2, stack_push (TYPE_INT) );
+                                       }
+                               break;
+
+                       case CMD_LDIV:
+                       case CMD_LREM:
+                               v2 = stack_pop (TYPE_LONG);
+                               v1 = stack_pop (TYPE_LONG);
+                               BRA (CMD_IFEQL, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
+
+                               if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+                                       OP2 (opcode, v1,v2, stack_push(TYPE_LONG));
+                                       DROP (v1);
+                                       DROP (v2);
+                                       }
+                               else {
+                                       stack_makesaved ();
+                                       BUILTIN2 (
+                                          (opcode == CMD_LDIV) ? 
+                                               ((functionptr) builtin_ldiv) 
+                                             : ((functionptr) builtin_lrem) 
+                                         ,v1,v2, stack_push (TYPE_LONG) );
+                                       }
+                               break;
+
+
+                       /*** Control transfer instructions ***/
+
+                       case CMD_IFEQ:
+                       case CMD_IFLT:
+                       case CMD_IFLE:
+                       case CMD_IFNE:
+                       case CMD_IFGT:
+                       case CMD_IFGE:
+                               target = block_find (p + code_get_s2 (p+1) );
+                               v = stack_pop (TYPE_INT);
+                               block_reach (target);
+                               BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
+                               break;
+
+                       case CMD_IFNULL:
+                       case CMD_IFNONNULL:
+                               target = block_find (p + code_get_s2 (p+1));
+                               v = stack_pop (TYPE_ADDRESS);
+                               block_reach (target);
+                               BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
+                               break;
+
+                       case CMD_IF_ICMPEQ:
+                       case CMD_IF_ICMPNE:
+                       case CMD_IF_ICMPLT:
+                       case CMD_IF_ICMPGT:
+                       case CMD_IF_ICMPLE:
+                       case CMD_IF_ICMPGE:
+                               target = block_find (p + code_get_s2 (p+1) );
+                               v2 = stack_pop (TYPE_INT);
+                               v1 = stack_pop (TYPE_INT);
+                               block_reach (target);
+                               BRA_N_DROP (opcode, v1,v2, NOVAR, target );
+                               break;
+
+                       case CMD_IF_ACMPEQ:
+                       case CMD_IF_ACMPNE:
+                               target = block_find (p + code_get_s2 (p+1) );
+                               v2 = stack_pop (TYPE_ADDRESS);
+                               v1 = stack_pop (TYPE_ADDRESS);
+                               block_reach (target);
+                               BRA_N_DROP (opcode, v1,v2, NOVAR, target);
+                               break;
+
+
+                       case CMD_GOTO:
+                               target = block_find (p + code_get_s2 (p+1) );
+                               goto do_goto;
+                       case CMD_GOTO_W:
+                               target = block_find (p + code_get_s4 (p+1) );
+                         do_goto:
+                               block_reach (target);
+                               BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, target );
+                               goto cleanup;
+
+
+                       case CMD_JSR:
+                               target = block_find (p + code_get_s2 (p+1) );
+                               goto do_jsr;
+                       case CMD_JSR_W:
+                               target = block_find (p + code_get_s4 (p+1) );
+                         do_jsr:
+                               {
+                           subroutineinfo *sub;
+
+                               ACTIVATE (stack_push (TYPE_ADDRESS) );
+
+                               sub = target->subroutine;
+                               if (!sub) {
+                                       sub = subroutine_new();
+                                       target->subroutine = sub;
+                                       }
+
+                               subroutine_set (sub);
+                               block_reach (target);
+                               subroutine_set (b->subroutine);
+
+                               BRA (CMD_JSR, NOVAR,NOVAR, stack_pop(TYPE_ADDRESS), target );
+
+                               while (! stack_isempty() ) {
+                                       v = stack_popany ( stack_topslots() );
+                                       DROP (v);
+                                       }
+
+                               if (sub->returnfinished) {
+                                       stackinfo *s = sub->returnstack;
+                                       stack_restore (s);
+                                       while (s) {
+                                               ACTIVATE (s->var);
+                                               s = s->prev;
+                                               }
+                                       block_reach ( block_find(nextp) );
+                                       }
+                               else {
+                                       basicblock *n = block_find(nextp);
+                                       n -> subroutine = b->subroutine;
+
+                                       chain_addlast (sub->callers, n );
+                                       }
+
+                               }
+                               goto cleanup;
+
+
+                       case CMD_RET:
+                               if (!iswide) {
+                                       v = local_get (code_get_u1 (p+1), TYPE_ADDRESS);
+                                       }
+                               else {
+                                       v = local_get (code_get_u2 (p+1), TYPE_ADDRESS);
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+
+                               {
+                               subroutineinfo *sub;
+                               basicblock *bb;
+
+                               sub = b->subroutine;
+                               if (!sub) panic ("RET outside of subroutine");
+                               if (sub->returnfinished) panic ("Multiple RET in a subroutine");
+
+                               sub->returnfinished = true;
+                               sub->returnstack = stack_get() ;
+
+                               while ( (bb = chain_first(sub->callers)) ) {
+                                       chain_remove (sub->callers);
+
+                                       subroutine_set (bb->subroutine);
+                                       block_reach ( bb );
+                                       subroutine_set (sub);
+                                       }
+
+                               BRA (CMD_RET, v,NOVAR, NOVAR, NULL);
+                               }
+                               goto cleanup;
+
+
+
+                       /*************** Function Return **************/
+
+                       case CMD_IRETURN:
+                               addreturnhandling();
+
+                               v = stack_pop (TYPE_INT);
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+                               goto cleanup;
+
+                       case CMD_LRETURN:
+                               addreturnhandling();
+
+                               v = stack_pop (TYPE_LONG);
+                               var_proposereg (v, reg_parlistresult(TYPE_LONG) );
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               var_proposereg (ve, reg_parlistexception() );
+                               BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+                               goto cleanup;
+
+                       case CMD_FRETURN:
+                               addreturnhandling();
+
+                               v = stack_pop (TYPE_FLOAT);
+                               var_proposereg (v, reg_parlistresult(TYPE_FLOAT) );
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               var_proposereg (ve, reg_parlistexception() );
+                               BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+                               goto cleanup;
+
+                       case CMD_DRETURN:
+                               addreturnhandling();
+
+                               v = stack_pop (TYPE_DOUBLE);
+                               var_proposereg (v, reg_parlistresult(TYPE_DOUBLE) );
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               var_proposereg (ve, reg_parlistexception() );
+                               BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+                               goto cleanup;
+
+                       case CMD_ARETURN:
+                               addreturnhandling();
+
+                               v = stack_pop (TYPE_ADDRESS);
+                               var_proposereg (v, reg_parlistresult(TYPE_ADDRESS) );
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               var_proposereg (ve, reg_parlistexception() );
+                               BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
+                               goto cleanup;
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+
+                       case CMD_RETURN:
+                               addreturnhandling();
+
+                               ve = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (NULL, ve);
+                               var_proposereg (ve, reg_parlistexception() );
+                               BRA_N_DROP (opcode, NOVAR,ve, NOVAR, NULL);
+#ifdef STATISTICS
+       count_pcmd_return++;
+#endif
+                               goto cleanup;
+
+
+                       case CMD_BREAKPOINT:
+                               break;
+
+
+
+                       /**************** Table Jumping *****************/
+
+                       case CMD_LOOKUPSWITCH:
+                               {       u4 p2 = ALIGN((p+1), 4);
+                                       basicblock *defaulttarget;
+                                       u4 num, i;
+
+                                       defaulttarget = block_find (p + code_get_s4 (p2) );
+                                       num = code_get_s4 (p2+4);
+
+                                       v = stack_pop (TYPE_INT);
+                                       for (i=0; i<num; i++) {
+                                               s4 value = code_get_s4 (p2 + 8 + 8*i);
+                                               target = block_find (p + code_get_s4 (p2 + 8 + 4 + 8*i) );
+
+                                               v1 = var_create (TYPE_INT);
+                                               v2 = var_create (TYPE_INT);
+                                               MOVE (TYPE_INT, v, v1);
+                                               LOADCONST_I (value, v2);
+                                               block_reach (target);
+                                               BRA_N_DROP (CMD_IF_ICMPEQ, v1,v2, NOVAR, target );
+                                               }
+
+                                       DROP (v);
+                                       block_reach (defaulttarget);
+                                       BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, defaulttarget );
+
+                                       nextp = p2 + 8 + 8*num;
+                                       goto cleanup;
+                               }
+                               break;
+
+                       case CMD_TABLESWITCH:
+                               {       u4 p2 = ALIGN((p+1), 4);
+                                       basicblock *target;
+                                       basicblock **targets;
+                                       s4 low,high, i;
+                                       
+                                       low = code_get_s4 (p2+4);
+                                       high = code_get_s4 (p2+8);
+                                       if (high<low) panic ("Tablejump range invalid");
+
+                                       v = stack_pop (TYPE_INT);
+
+                                       target = block_find (p + code_get_s4 (p2) );
+                                       block_reach(target);
+
+                                       v1 = var_create (TYPE_INT);
+                                       LOADCONST_I (high, v1);
+                                       BRA (CMD_IF_ICMPGT, v,v1, NOVAR, target);
+                                       DROP (v1);
+                                       
+                                       if (low!=0) {
+                                               v1 = var_create (TYPE_INT);
+                                               v2 = var_create (TYPE_INT);
+                                               LOADCONST_I (low, v1);
+                                               OP2 (CMD_ISUB, v,v1, v2);
+                                               DROP (v1);
+                                               DROP (v);
+                                               v = v2;
+                                               } 
+                                       BRA (CMD_IFLT, v,NOVAR, NOVAR, target);
+                                               
+                                       targets = DMNEW (basicblock*, (high-low)+1);
+                                       for (i=0; i < (high-low)+1; i++) {
+                                               target = block_find (p + code_get_s4 (p2 + 12 + 4*i) );
+                                               block_reach (target);
+
+                                               targets[i] = target;
+                                               }
+
+                                       TABLEJUMP (v, (high-low)+1, targets);
+                                       DROP (v);
+
+                                       nextp = p2 + 12 + 4 * ((high-low)+1);
+                                       goto cleanup;
+                               }
+                               break;
+
+
+                       /************ Manipulating Object Fields ********/
+
+                       case CMD_PUTSTATIC:
+                       case CMD_GETSTATIC:
+                       case CMD_PUTFIELD:
+                       case CMD_GETFIELD:
+
+                               poolindex = code_get_u2 (p+1);
+                               { constant_FMIref *fr;
+                                 fieldinfo *fi;
+
+                                       fr = class_getconstant (class, poolindex, CONSTANT_Fieldref);
+                                       fi = class_findfield (fr->class, fr->name, fr->descriptor);
+
+                                       switch (opcode) {
+                                       case CMD_PUTSTATIC:
+                                               compiler_addinitclass (fr->class);
+
+                                               v1 = var_create (TYPE_ADDRESS);
+                                               v = stack_pop (fi->type);
+                                               LOADCONST_A (&(fi->value), v1);
+
+                                               MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, 0);
+                                               DROP (v);
+                                               DROP (v1);
+                                               break;
+
+                                       case CMD_GETSTATIC:
+                                               compiler_addinitclass (fr->class);
+
+                                               v1 = var_create (TYPE_ADDRESS);
+                                               v = stack_push (fi->type);
+                                               LOADCONST_A (&(fi->value), v1);
+
+                                               MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, 0);
+                                               DROP (v1);
+                                               break;
+
+
+                                       case CMD_PUTFIELD:
+                                               v = stack_pop (fi->type);
+                                               v1 = stack_pop (TYPE_ADDRESS);
+                                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                                       BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+                                                       }
+                                               MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, fi->offset);
+                                               DROP (v);
+                                               DROP (v1);
+                                               break;
+
+                                       case CMD_GETFIELD:
+                                               v1 = stack_pop (TYPE_ADDRESS);
+                                               v = stack_push (fi->type);
+                                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                                       BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
+                                                       }
+                                               MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, fi->offset);
+                                               DROP (v1);
+                                               break;
+
+
+                                       }
+                               }
+                               break;
+
+
+                       /*** Method invocation ***/
+
+                       case CMD_INVOKEVIRTUAL:
+                       case CMD_INVOKESPECIAL:
+                       case CMD_INVOKESTATIC:
+                       case CMD_INVOKEINTERFACE:
+                       
+                               count_calls ++;
+                       
+                               { constant_FMIref *mr;
+                                 methodinfo *mi;
+                                 u4 i;
+                                 s4 paramnum;
+                                 u1 *paramtypes;
+                                 s4 returntype;
+                                 varid *params;
+                                 bool stat = (opcode == CMD_INVOKESTATIC);
+
+                               if (opcode==CMD_INVOKEINTERFACE) {
+                                       poolindex = code_get_u2 (p+1);
+                                       mr = class_getconstant (class, poolindex, CONSTANT_InterfaceMethodref);
+                                       }
+                               else {
+                                       poolindex = code_get_u2 (p+1);
+                                       mr = class_getconstant (class, poolindex, CONSTANT_Methodref);
+                                       }
+
+                               mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+
+                               if ( ((mi->flags & ACC_STATIC) != 0) != stat)
+                                       panic ("Static/Nonstatic mismatch on method call");
+
+                               descriptor2types (mi->descriptor, stat,
+                         &paramnum, &paramtypes, &returntype);
+                   mi->paramcount = paramnum;
+
+                               params = DMNEW (varid, paramnum);
+                               for (i=0; i<paramnum; i++) {
+                                       params[paramnum-i-1] = stack_pop (paramtypes[paramnum-i-1]);
+                                       }
+
+                               stack_makesaved();
+
+                               if ((!stat) && checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                       BRA (CMD_IFNULL, params[0],NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
+                                       }
+
+                               ve = var_create (TYPE_ADDRESS);
+                               if (returntype != TYPE_VOID) {
+                                       v = stack_push (returntype);
+                                       METHOD (opcode, mi, NULL, paramnum, params, v,  ve);
+                                       }
+                               else {
+                                       METHOD (opcode, mi, NULL, paramnum, params, NOVAR, ve);
+                                       }
+
+                               BRA (CMD_IFNONNULL, ve,NOVAR, NOVAR, EXFORWARDER(ve) );
+                               DROP (ve);
+
+                               }
+                               break;
+
+
+                       /********* Exception Handling *****************/
+
+                       case CMD_ATHROW:
+                               v = stack_pop (TYPE_ADDRESS);
+                               if (checknull) {
+#ifdef STATISTICS
+                                       count_check_null++;
+#endif
+                                       BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_NullPointerException) );
+                                       }
+                               BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR,  EXFORWARDER (v) );
+                               DROP (v);
+                               goto cleanup;
+
+
+                       /***** Miscellaneous Object Operations ****/
+
+                       case CMD_NEW:
+                               poolindex = code_get_u2 (p+1);
+                               { classinfo *ci;
+
+                               ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+                               v1 = var_create (TYPE_ADDRESS);
+                               LOADCONST_A (ci, v1);
+
+                               stack_makesaved ();
+
+                               v = stack_push (TYPE_ADDRESS);
+                               BUILTIN1 ((functionptr) builtin_new, v1, v);
+                               BRA (CMD_IFNULL, v,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_OutOfMemoryError) );
+
+                               }
+                               break;
+
+
+                       case CMD_CHECKCAST:
+                               poolindex = code_get_u2 (p+1);
+
+                               if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+                                       /* cast-check auf Array-Typ! */
+
+                                       constant_arraydescriptor *desc =
+                                         class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+                                       v = stack_pop (TYPE_ADDRESS);
+                                       stack_repush (v);
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       MOVE (TYPE_ADDRESS, v,v1);
+                                       v2 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (desc, v2);
+
+                                       stack_makesaved ();
+                                       ve = var_create (TYPE_INT);
+                                       BUILTIN2 ((functionptr) builtin_checkarraycast, v1,v2, ve);
+
+                                       BRA (CMD_IFEQ,ve,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_ClassCastException) );
+                                       DROP (ve);
+                                       }
+                               else {
+                                       /* cast-check auf Object-Typ */
+
+                                       classinfo *ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+                                       v = stack_pop (TYPE_ADDRESS);
+                                       stack_repush (v);
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       MOVE (TYPE_ADDRESS, v, v1);
+                                       v2 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (ci, v2);
+
+                                       stack_makesaved ();
+                                       ve = var_create (TYPE_INT);
+                                       BUILTIN2 ((functionptr) builtin_checkcast, v1,v2, ve);
+
+                                       BRA (CMD_IFEQ,ve,NOVAR, NOVAR,  EXCREATOR(proto_java_lang_ClassCastException) );
+                                       DROP (ve);
+                                       }
+
+                               break;
+
+
+                       case CMD_INSTANCEOF:
+                               poolindex = code_get_u2 (p+1);
+
+                               if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
+                                       /* cast-check auf Array-Typ! */
+
+                                       constant_arraydescriptor *desc =
+                                         class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
+
+                                       v = stack_pop (TYPE_ADDRESS);
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (desc, v1);
+
+                                       stack_makesaved ();
+
+                                       BUILTIN2 ((functionptr) builtin_arrayinstanceof, v,v1,
+                                                     stack_push (TYPE_INT) );
+                                       }
+                               else {
+                                       classinfo *ci;  
+                                       ci = class_getconstant (class, poolindex, CONSTANT_Class);
+
+                                       v = stack_pop (TYPE_ADDRESS);
+                                       v1 = var_create (TYPE_ADDRESS);
+                                       LOADCONST_A (ci, v1);
+
+                                       stack_makesaved ();
+
+                                       BUILTIN2 ((functionptr) builtin_instanceof, v,v1,
+                                                     stack_push (TYPE_INT) );
+                                       }
+                               break;
+
+
+
+
+                       /*************** Monitors ************************/
+
+                       case CMD_MONITORENTER:
+                               if (checksync) {
+                                       v = stack_pop (TYPE_ADDRESS);
+                                       if (checknull) {
+#ifdef STATISTICS
+                                               count_check_null++;
+#endif
+                                               BRA (CMD_IFNULL, v, NOVAR, NOVAR,
+                                                    EXCREATOR(proto_java_lang_NullPointerException));
+                                               }
+                                       BUILTIN1 ((functionptr) builtin_monitorenter, v, NOVAR);
+                               } else {
+                                       DROP (stack_pop (TYPE_ADDRESS));
+                                       }                                       
+                               break;
+
+                       case CMD_MONITOREXIT:
+                               if (checksync) {
+                                       BUILTIN1 ((functionptr) builtin_monitorexit, 
+                                          stack_pop(TYPE_ADDRESS), NOVAR );
+                               } else {
+                                       DROP (stack_pop (TYPE_ADDRESS));
+                                       }                                       
+                               break;
+
+
+
+
+                       /************** any other Basic-Operation **********/
+
+
+                       default:
+                               {
+                               stdopdescriptor *s = stdopdescriptors[opcode];
+                               if (s) {
+                                       v2 = NULL;
+                                       if (s->type_s2 != TYPE_VOID) v2 = stack_pop(s->type_s2);
+                                       v1 = stack_pop(s->type_s1);
+
+                                       if (s->supported) {
+                                               v = stack_push (s->type_d);
+                                               if (v2) {
+                                                       OP2 (opcode, v1,v2, v);
+                                                       DROP (v1);
+                                                       DROP (v2);
+                                                       }
+                                               else {
+                                                       OP1 (opcode, v1, v);
+                                                       DROP (v1);
+                                                       }
+                                               }
+                                       else {
+                                               stack_makesaved ();
+                                               v = stack_push (s->type_d);
+                                               if (v2) {
+                                                       BUILTIN2 (s->builtin, v1,v2, v);
+                                                       }
+                                               else {
+                                                       BUILTIN1 (s->builtin, v1, v);
+                                                       }
+                                               }
+                                       }
+                                               
+
+                       /*************** invalid Opcode ***************/                
+                                       
+                               else {
+                                       sprintf (logtext, "Invalid opcode %d at position %ld",
+                                                  opcode, (long int) p);
+                                       error ();
+                                       }
+
+                               }
+                               
+                               break;
+                               
+
+                       } /* end switch */
+
+
+               p = nextp;
+
+               if ( block_isany (p) ) {
+                       block_reach ( block_find (p) );
+                       goto cleanup;
+                       }
+
+               } /* end for */
+
+
+cleanup:
+       pcmd_untieall();
+}
+
diff --git a/comp/pcmd.c b/comp/pcmd.c
new file mode 100644 (file)
index 0000000..8279fa3
--- /dev/null
@@ -0,0 +1,706 @@
+/********************************** comp/pcmd.c ********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       contains the parser functions which generate pseude commands and
+       eliminating unnecessary copy instructions
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/09/22
+
+*******************************************************************************/
+
+
+list *pcmdlist;  /* list of pseudo commands */
+
+
+/***************************** support functions ******************************/
+
+static void pcmd_init (list *pl)
+{
+       pcmdlist = pl;
+}
+
+
+static void pcmd_realmove (u2 type, varid source, varid dest)
+{
+       pcmd *c = DNEW(pcmd);
+       c -> tag = TAG_MOVE;
+       c -> opcode = CMD_MOVE;
+       c -> source1 = source;
+       c -> source2 = NOVAR;
+       c -> source3 = NOVAR;
+       c -> dest = dest;
+       c -> u.move.type = type;
+       list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+       count_pcmd_move++;
+#endif
+}
+
+
+static void pcmd_invalidatevar (varid v)
+{
+       varid c;
+       
+       if (!var_isoriginal(v) ) {
+               var_unlinkcopy (v);
+               }
+       else {
+               while ( (c = var_nextcopy (v)) != NULL) {
+                       pcmd_realmove (var_type(v), v,c);
+                       var_unlinkcopy (c);
+                       }
+                       
+               }
+}
+
+
+static void pcmd_untievar (varid v)
+{
+       varid c;
+       
+       if (!var_isoriginal(v)) {
+               pcmd_realmove (var_type(v), var_findoriginal(v), v);
+               var_unlinkcopy (v);
+               }
+       else {
+               while ( (c = var_nextcopy(v)) != NULL) {
+                       pcmd_realmove (var_type(v), v, c);
+                       var_unlinkcopy (c);
+                       }
+               }
+}
+
+
+static void pcmd_untieall ()
+{
+       varid v;
+       
+       while ( (v = var_nextcopiedvar()) != NULL) {
+               pcmd_realmove (var_type(v), var_findoriginal(v), v);
+               var_unlinkcopy (v);
+               }
+}
+
+
+/********************** generation of pseudo commands *************************/
+
+static void pcmd_drop (varid var)
+{
+       pcmd *c = DNEW(pcmd);
+
+       if (var_isoriginal(var)) {
+               pcmd_invalidatevar (var);
+       
+               c -> tag = TAG_DROP;
+               c -> opcode = CMD_DROP;
+               c -> dest = var;
+               c -> source1 = c -> source2 = c -> source3 = NOVAR;
+               list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+       count_pcmd_drop++;
+#endif
+               }
+       else {
+               pcmd_invalidatevar (var);
+               }
+}
+
+
+static void pcmd_activate (varid var)
+{
+       pcmd *c = DNEW(pcmd);
+       
+       pcmd_untieall();
+
+       c -> tag = TAG_ACTIVATE;
+       c -> opcode = CMD_ACTIVATE;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_activ++;
+#endif
+}
+
+
+static void pcmd_loadconst_i (s4 val, varid var)
+{
+       pcmd *c = DNEW (pcmd);
+       c -> tag = TAG_LOADCONST_I;
+       c -> opcode = CMD_LOADCONST_I;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;     
+       c -> u.i.value = val;
+
+       pcmd_invalidatevar (var);
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       if (val == 0)
+               count_pcmd_zero++;
+       count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_l (s8 val, varid var)
+{
+       pcmd *c = DNEW (pcmd);
+       c -> tag = TAG_LOADCONST_L;
+       c -> opcode = CMD_LOADCONST_L;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;     
+       c -> u.l.value = val;
+
+       pcmd_invalidatevar (var);
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       if (val == 0)
+               count_pcmd_zero++;
+       count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_f (float val, varid var)
+{
+       pcmd *c = DNEW (pcmd);
+       c -> tag = TAG_LOADCONST_F;
+       c -> opcode = CMD_LOADCONST_F;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;     
+       c -> u.f.value = val;
+
+       pcmd_invalidatevar (var);
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_d (double val, varid var)
+{
+       pcmd *c = DNEW (pcmd);
+       c -> tag = TAG_LOADCONST_D;
+       c -> opcode = CMD_LOADCONST_D;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;     
+       c -> u.d.value = val;
+
+       pcmd_invalidatevar (var);
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_loadconst_a (void *val, varid var)
+{
+       pcmd *c = DNEW (pcmd);
+       c -> tag = TAG_LOADCONST_A;
+       c -> opcode = CMD_LOADCONST_A;
+       c -> dest = var;
+       c -> source1 = c -> source2 = c -> source3 = NOVAR;     
+       c -> u.a.value = val;
+
+       pcmd_invalidatevar (var);
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       if (val == NULL)
+               count_pcmd_zero++;
+       count_pcmd_load++;
+#endif
+}
+
+
+static void pcmd_move (u2 type, varid source, varid dest)
+{
+       pcmd_invalidatevar (dest);
+       var_makecopy ( var_findoriginal(source), dest);
+}
+
+
+static void pcmd_move_n_drop (u2 type, varid source, varid dest)
+{
+       pcmd *c;
+       
+       pcmd_untievar (source);
+       pcmd_untievar (dest);
+
+#ifdef STATISTICS
+       count_pcmd_store++;
+#endif
+       c = list_last (pcmdlist);
+       while (c) {
+               switch (c->tag) {
+               case TAG_LOADCONST_I:
+                       if (c->dest == source) { c->dest = dest; return; }
+#ifdef STATISTICS
+                               count_pcmd_const_store++;
+#endif
+                       goto nothingfound;
+               case TAG_LOADCONST_L:
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+               case TAG_LOADCONST_F:
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+               case TAG_LOADCONST_D:
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+               case TAG_LOADCONST_A:
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+               case TAG_OP:    
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+               case TAG_MEM:
+                       if (c->dest == source) { c->dest = dest; return; }
+                       goto nothingfound;
+
+               case TAG_DROP:
+                       break;
+               default:
+                       goto nothingfound;
+               } /* end switch */
+               
+               c = list_prev (pcmdlist, c);
+               }
+
+nothingfound:
+       var_makecopy ( source, dest);
+       pcmd_drop (source);
+#ifdef STATISTICS
+       count_pcmd_store_comb++;
+#endif
+}
+
+
+static void pcmd_iinc (s4 val, varid sourcedest)
+{
+       pcmd *c = DNEW (pcmd);
+
+       pcmd_invalidatevar (sourcedest);
+
+       c -> tag = TAG_OP;
+       c -> opcode = CMD_IINC;
+       c -> source1 = var_findoriginal(sourcedest);
+       c -> source2 = NOVAR;
+       c -> source3 = NOVAR;   
+       c -> dest = sourcedest;
+       c -> u.i.value = val;
+
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_op++;
+#endif
+}
+
+
+static void pcmd_op (u1 opcode, 
+             varid source1, varid source2, varid source3, varid dest)
+{
+       pcmd *c;
+       
+#ifdef STATISTICS
+       c = list_last (pcmdlist);
+       if (c && (c->tag == TAG_LOADCONST_I))
+               switch (opcode) {
+                       case CMD_IASTORE:
+                       case CMD_BASTORE:
+                       case CMD_CASTORE:
+                       case CMD_SASTORE:
+                               count_pcmd_const_store++;
+                               break;
+                       case CMD_IADD:
+                       case CMD_ISUB:
+                       case CMD_IMUL:
+                       case CMD_ISHL:
+                       case CMD_ISHR:
+                       case CMD_IUSHR:
+                       case CMD_IAND:
+                       case CMD_IOR:
+                       case CMD_IXOR:
+                               count_pcmd_const_alu++;
+                       }
+#endif
+       c = DNEW(pcmd);
+       if (dest) pcmd_invalidatevar (dest);
+       
+       c -> tag = TAG_OP;
+       c -> opcode = opcode;
+       c -> source1 = source1 ? var_findoriginal(source1) : NOVAR;
+       c -> source2 = source2 ? var_findoriginal(source2) : NOVAR;
+       c -> source3 = source3 ? var_findoriginal(source3) : NOVAR;
+       c -> dest = dest;
+       list_addlast (pcmdlist, c);
+#ifdef STATISTICS
+       count_pcmd_op++;
+#endif
+}
+
+
+static void pcmd_mem (u1 opcode, u2 type, varid base, varid source, 
+                        varid dest, u2 offset) 
+{
+       pcmd *c;
+
+#ifdef STATISTICS
+       c = list_last (pcmdlist);
+       if (c && (c->tag == TAG_LOADCONST_I) && (opcode == CMD_PUTFIELD))
+               count_pcmd_const_store++;
+#endif
+       c = DNEW(pcmd);
+       if (dest) pcmd_invalidatevar (dest);
+       
+       c -> tag = TAG_MEM;
+       c -> opcode = opcode;
+       c -> source1 = base   ? var_findoriginal(base) : NOVAR;
+       c -> source2 = source ? var_findoriginal(source) : NOVAR;
+       c -> source3 = NOVAR;
+       c -> dest = dest;
+       c -> u.mem.type = type;
+       c -> u.mem.offset = offset;
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_mem++;
+#endif
+}
+
+
+static void pcmd_bra (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
+{
+       pcmd *c;
+       varid or1,or2;
+       
+#ifdef STATISTICS
+       c = list_last (pcmdlist);
+       if (c && (c->tag == TAG_LOADCONST_I))
+               switch (opcode) {
+                       case CMD_IF_ICMPEQ:
+                       case CMD_IF_ICMPNE:
+                       case CMD_IF_ICMPLT:
+                       case CMD_IF_ICMPGT:
+                       case CMD_IF_ICMPLE:
+                       case CMD_IF_ICMPGE:
+                               count_pcmd_const_bra++;
+                       }
+#endif
+       c = DNEW(pcmd);
+       or1 = s1 ? var_findoriginal (s1) : NOVAR;
+       or2 = s2 ? var_findoriginal (s2) : NOVAR;
+       
+       pcmd_untieall();
+       
+       c -> tag = TAG_BRA;
+       c -> opcode = opcode;
+       c -> source1 = or1;
+       c -> source2 = or2;
+       c -> source3 = NOVAR;
+       c -> dest = dest;
+       c -> u.bra.target = target;
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_bra++;
+#endif
+}
+
+
+static void pcmd_trace (void *method)
+{
+       pcmd *c;
+       
+       isleafmethod = false;
+       
+       c = DNEW(pcmd);
+       c -> tag = TAG_BRA;
+       c -> opcode = CMD_TRACEBUILT;
+       c -> source1 = NOVAR;
+       c -> source2 = NOVAR;
+       c -> source3 = NOVAR;
+       c -> dest = NOVAR;
+       c -> u.a.value = method;
+       list_addlast (pcmdlist, c);
+}
+
+
+static void pcmd_bra_n_drop (u1 opcode, varid s1, varid s2, varid dest, basicblock *target)
+{
+       pcmd *c;
+       varid or1=NOVAR,or2=NOVAR;
+       bool isor1=false,isor2=false;
+       
+#ifdef STATISTICS
+       c = list_last (pcmdlist);
+       if (c && (c->tag == TAG_LOADCONST_I))
+               switch (opcode) {
+                       case CMD_IF_ICMPEQ:
+                       case CMD_IF_ICMPNE:
+                       case CMD_IF_ICMPLT:
+                       case CMD_IF_ICMPGT:
+                       case CMD_IF_ICMPLE:
+                       case CMD_IF_ICMPGE:
+                               count_pcmd_const_bra++;
+                       }
+#endif
+       c = DNEW(pcmd);
+       if (s1!=NOVAR) {
+               or1 = var_findoriginal (s1); 
+           if (! (isor1 = var_isoriginal(s1)) ) var_unlinkcopy (s1);
+               }
+       if (s2!=NOVAR) {
+               or2 = var_findoriginal (s2);
+               if (! (isor2 = var_isoriginal (s2)) ) var_unlinkcopy (s2);
+               }
+
+       pcmd_untieall();
+
+       c -> tag = TAG_BRA;
+       c -> opcode = opcode;
+       c -> source1 = or1;
+       c -> source2 = or2;
+       c -> source3 = NOVAR;
+       c -> dest = dest;
+       c -> u.bra.target = target;
+       list_addlast (pcmdlist, c);
+       
+       if (isor1) pcmd_drop (s1);
+       if (isor2) pcmd_drop (s2);
+
+#ifdef STATISTICS
+       count_pcmd_bra++;
+#endif
+}
+
+
+static void pcmd_tablejump (varid s, u4 targetcount, basicblock **targets)
+{
+       pcmd *c = DNEW(pcmd);
+       
+       pcmd_untieall();
+       
+       c -> tag = TAG_TABLEJUMP;
+       c -> opcode = CMD_TABLEJUMP;
+       c -> source1 = var_findoriginal(s);
+       c -> source2 = NOVAR;
+       c -> source3 = NOVAR;
+       c -> dest = NOVAR;
+       c -> u.tablejump.targetcount = targetcount;
+       c -> u.tablejump.targets = targets;
+       list_addlast (pcmdlist, c);
+
+#ifdef STATISTICS
+       count_pcmd_table++;
+#endif
+}
+
+
+/******* ATTENTION: Method does DROP automatically !!!!! ****/
+
+static void pcmd_method (int opcode, methodinfo *mi, functionptr builtin, 
+                         int paramnum, varid *params, varid result, varid exceptionvar)
+{
+       varid v;
+       int i;
+
+       pcmd *c = DNEW(pcmd);
+       
+       pcmd_untieall();
+                                       
+       isleafmethod = false;
+
+       reg_parlistinit();
+       for (i = 0; i < paramnum; i++) {
+               v = params[i];
+               var_proposereg(v, reg_parlistpar(var_type(v)));
+               }
+               
+       if (result) {
+               var_proposereg(result, reg_parlistresult(var_type(result)));
+               }
+       if (exceptionvar) {
+               exceptionvar -> reg = reg_parlistexception();
+               }
+
+       c -> tag = TAG_METHOD;
+       c -> opcode = opcode;
+       c -> source1 = c -> source2 = c -> source3 = NULL;
+       c -> dest = result;
+       c -> u.method.method = mi;
+       c -> u.method.builtin = builtin;
+       c -> u.method.paramnum = paramnum;
+       c -> u.method.params = params;
+       c -> u.method.exceptionvar = exceptionvar;
+       list_addlast (pcmdlist, c);
+       
+       for (i = 0; i < paramnum; i++) pcmd_drop(params[i]);
+       
+#ifdef STATISTICS
+       count_pcmd_met++;
+#endif
+}
+
+
+
+static void pcmd_builtin1 (functionptr builtin, varid v1, varid result)
+{
+       varid *args = DMNEW (varid, 1);
+       args[0] = v1;
+       pcmd_method (CMD_BUILTIN, NULL, builtin, 1, args, result,NOVAR);
+}
+
+static void pcmd_builtin2 (functionptr builtin, varid v1, varid v2, varid result)
+{
+       varid *args = DMNEW (varid, 2);
+       args[0] = v1;
+       args[1] = v2;
+       pcmd_method (CMD_BUILTIN, NULL, builtin, 2, args, result, NOVAR);
+}
+
+static void pcmd_builtin3 (functionptr builtin, varid v1, varid v2, varid v3, varid result)
+{
+       varid *args = DMNEW (varid, 3);
+       args[0] = v1;
+       args[1] = v2;
+       args[2] = v3;
+       pcmd_method (CMD_BUILTIN, NULL, builtin, 3, args, result, NOVAR);
+}
+
+
+static void pcmd_display (pcmd *c)
+{
+       int i;
+
+       switch (c -> tag) {
+               case TAG_LOADCONST_I:
+                       printf ("   LOADCONST_I #%ld -> ", 
+                                         (long int) c -> u.i.value);
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+               case TAG_LOADCONST_L:  
+#if U8_AVAILABLE
+                       printf ("   LOADCONST_L #%ld -> ", (long int) c -> u.l.value);
+#else
+                       printf ("   LOADCONST_L #HI: %ld LO: %ld -> ", 
+                         (long int) c->u.l.value.high, (long int) c->u.l.value.low );
+#endif
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+               case TAG_LOADCONST_F:  
+                       printf ("   LOADCONST_F #%f -> ", (double) c -> u.f.value);                             
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+               case TAG_LOADCONST_D:  
+                       printf ("   LOADCONST_D #%f -> ", c ->  u.d.value);
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+               case TAG_LOADCONST_A:  
+                       printf ("   LOADCONST_A #%p -> ", c ->  u.a.value);
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+                       
+               case TAG_MOVE:
+                       printf ("   MOVE_%1d      ", c -> u.move.type);
+                       var_display (c-> source1);      
+                       printf (" -> ");
+                       var_display (c -> dest);
+                       printf ("\n");
+                       break;
+                       
+               case TAG_OP:
+                       printf ("   OP%3d       ", c -> opcode);
+                       var_display (c -> source1);
+                       printf (", ");
+                       var_display (c -> source2);
+                       printf (", ");
+                       var_display (c -> source3);
+                       printf (" -> ");
+                       var_display (c -> dest );
+                       printf ("\n");
+                       break;
+
+               case TAG_BRA:
+                       printf ("   BRA%3d     (", c -> opcode);
+                       var_display (c -> source1);
+                       printf (", ");
+                       var_display (c -> source2);
+                       printf (" -> ");
+                       var_display (c -> dest);
+                       if (c->u.bra.target) {
+                               printf (") to pos %ld\n", 
+                                  (long int) c -> u.bra.target -> jpc );
+                               }
+                       else printf (")\n");
+                       break;
+                       
+               case TAG_TABLEJUMP:
+                       printf ("   TABLEJUMP     ");
+                       var_display (c -> source1);
+                       printf ("\n");
+                       for (i=0; i < (int) c->u.tablejump.targetcount; i++) {
+                               printf ("      %d: to pos %ld\n", (int) i,
+                                  (long int) c ->u.tablejump.targets[i] -> jpc );
+                               }
+                       break;
+
+               case TAG_MEM:
+                       printf ("   MEM%3d_%d    ",  c -> opcode, c -> u.mem.type);
+                       var_display (c -> source2);
+                       printf ("/");
+                       var_display (c -> dest);
+                       printf ("  <->  ");
+                       printf ("%d [", (int) (c -> u.mem.offset) );
+                       var_display (c -> source1 );
+                       printf ("]\n");
+                       break;
+
+               case TAG_METHOD:
+                       printf ("   METHOD%3d   ", c -> opcode);
+                       for (i=0; i < c -> u.method.paramnum; i++) {
+                          var_display (c -> u.method.params[i]);
+                          }
+                       printf (" -> ");
+                       var_display (c -> dest);
+                       printf ("/");
+                       var_display (c->u.method.exceptionvar);
+                       printf ("\n");
+                       break;
+
+               case TAG_DROP:
+                       printf ("   [ DROP      ");
+                       var_display (c-> dest);
+                       printf (" ]\n");
+                       break;
+               case TAG_ACTIVATE:
+                       printf ("   [ ACTIVATE      ");
+                       var_display (c-> dest);
+                       printf (" ]\n");
+                       break;
+
+               default:
+                       printf ("   ???\n");
+                       break;
+               }
+
+}
diff --git a/comp/reg.c b/comp/reg.c
new file mode 100644 (file)
index 0000000..c4b9bcf
--- /dev/null
@@ -0,0 +1,525 @@
+/******************************* comp/reg.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       The register-manager.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/23
+
+*******************************************************************************/
+
+/*********************** Structure of a register info *************************/
+
+#define REG_TYPE_FLT        1    /* integer or floating point type       */
+#define REG_SIZE_DBL        2    /* int/single or long/double            */
+#define REG_INMEMORY        4    /* true if register is in memory        */
+#define REG_ISFREE          8    /* true if register is currently free   */
+#define REG_ISUNUSED        16   /* true if register never has been used */
+#define REG_ISFREEUNUSED    24
+
+#define IS_INT_LNG_REG(a)   (!((a)&REG_TYPE_FLT))
+#define IS_FLT_DBL_REG(a)   ((a)&REG_TYPE_FLT)
+
+#define REGTYPE_INT    0
+#define REGTYPE_FLT    1
+#define REGTYPE_LNG    2
+#define REGTYPE_DBL    3
+
+#define REGTYPE(a)     ((a) & 3)
+
+typedef struct reginfo {
+       int  typeflags;                   /* register type, size and flags        */
+       int  num;                         /* register number or stack offset      */
+       list *waitlist;                   /* free list for register allocation    */
+       listnode linkage;
+} reginfo;
+
+
+
+static reginfo *intregs = NULL;       /* table for the integer registers      */
+static reginfo *floatregs = NULL;     /* table for the float registers        */
+static int intregsnum;                /* absolute number of integer registers */
+static int floatregsnum;              /* absolute number of float registers   */ 
+
+static int intreg_ret;                /* register to return integer values    */
+static int intreg_exc;                /* register to return exception value   */
+static int intreg_arg1;               /* register for first integer argument  */
+static int intreg_argnum;             /* number of integer argument registers */
+
+static int floatreg_ret;              /* register for return float values     */
+static int floatreg_arg1;             /* register for first float argument    */
+static int floatreg_argnum;           /* number of float argument registers   */
+
+
+static list savedintslist;     /* free saved int registers during allocation  */
+static list savedfloatslist;   /* free saved float registers during allocation*/
+static list scratchintslist;   /* free temp int registers during allocation   */
+static list scratchfloatslist; /* free temp float registers during allocation */
+static int *freeintregs;       /* free int registers table                    */
+static int *freefloatregs;     /* free float registers table                  */
+
+static int savedregs_num;      /* total number of registers to be saved       */
+static int localvars_num;      /* total number of variables to spilled        */
+static int arguments_num;      /* size of parameter field in the stackframe   */
+
+
+
+/****************** function reg_init ******************************************
+
+       initialises the register-allocator
+       
+*******************************************************************************/
+
+static void reg_init()
+{
+       int n;
+       
+       if (!intregs) {
+               for (intregsnum=0; regdescint[intregsnum] != REG_END; intregsnum++);
+               intregs = MNEW (reginfo, intregsnum);
+               freeintregs = MNEW (int, intregsnum + 2);
+               *freeintregs++ = 0;
+               freeintregs[intregsnum] = 0;
+
+               intreg_arg1 = -1;
+               for (n=0; n<intregsnum; n++) {
+                       intregs[n].typeflags = 0;
+                       intregs[n].num = n;
+                       intregs[n].waitlist = NULL;
+                       freeintregs[n] = 0;
+                   
+                       switch (regdescint[n]) {
+                               case REG_RES: break;
+                               case REG_RET: intreg_ret = n; 
+                                             break;
+                               case REG_EXC: intreg_exc = n;
+                                             break;
+                               case REG_SAV: intregs[n].waitlist = &(savedintslist);
+                                             freeintregs[n] = 1;
+                                             break;
+                               case REG_TMP: intregs[n].waitlist = &(scratchintslist);
+                                             freeintregs[n] = 1;
+                                             break;
+                               case REG_ARG: if (intreg_arg1 < 0) intreg_arg1 = n;
+                                             intreg_argnum++;
+                                             break;
+                               }
+                       }
+                                       
+               
+               for (floatregsnum=0; regdescfloat[floatregsnum] != REG_END; floatregsnum++);
+               floatregs = MNEW (reginfo, floatregsnum);
+               freefloatregs = MNEW (int, floatregsnum + 2);
+               *freefloatregs++ = 0;
+               freefloatregs[floatregsnum] = 0;
+
+        floatreg_arg1 = -1;
+               for (n=0; n<floatregsnum; n++) {
+                       floatregs[n].typeflags = REG_TYPE_FLT;
+                       floatregs[n].num = n;
+                       floatregs[n].waitlist = NULL;
+                       freefloatregs[n] = 0;
+
+                       switch (regdescfloat[n]) {
+                               case REG_RES: break;
+                               case REG_RET: floatreg_ret = n; 
+                                             break;
+                               case REG_EXC: panic ("can not use floating-reg as exception");
+                                             break;
+                               case REG_SAV: floatregs[n].waitlist = &(savedfloatslist);
+                                             freefloatregs[n] = 1;
+                                             break;
+                               case REG_TMP: floatregs[n].waitlist = &(scratchfloatslist);
+                                             freefloatregs[n] = 1;
+                                             break;
+                               case REG_ARG: if (floatreg_arg1 < 0) floatreg_arg1 = n;
+                                             floatreg_argnum++;
+                                             break;
+                               }
+                       }
+                                       
+               }
+                                       
+
+       list_init (&savedintslist, OFFSET(reginfo, linkage));
+       list_init (&savedfloatslist, OFFSET(reginfo, linkage));
+       list_init (&scratchintslist, OFFSET(reginfo, linkage));
+       list_init (&scratchfloatslist, OFFSET(reginfo, linkage));
+       
+       for (n=0; n<intregsnum; n++) {
+               intregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
+               if (intregs[n].waitlist) 
+                       list_addlast(intregs[n].waitlist, intregs+n);
+       }
+       for (n=0; n<floatregsnum; n++) {
+               floatregs[n].typeflags |= REG_ISFREE | REG_ISUNUSED;
+               if (floatregs[n].waitlist) 
+                       list_addlast(floatregs[n].waitlist, floatregs+n);
+               }
+       
+       
+       localvars_num = 0;
+       arguments_num = 0;
+}
+
+
+/********************** function reg_close *************************************
+
+       releases all allocated space for registers
+
+*******************************************************************************/
+
+static void reg_close ()
+{
+       if (intregs) MFREE (intregs, reginfo, intregsnum);
+       if (floatregs) MFREE (floatregs, reginfo, floatregsnum);
+}
+
+
+/********************* function reg_free ***************************************
+
+       put back a register which has been allocated by reg_allocate into the
+       corresponding free list
+       
+*******************************************************************************/
+
+static void reg_free (reginfo *ri)
+{
+       ri -> typeflags |= REG_ISFREE;
+
+       if (ri->waitlist) {
+               if (ri->typeflags & REG_INMEMORY)
+                       list_addlast  (ri->waitlist, ri);
+               else {
+#if (WORDSIZE == 4)
+                       reginfo *ri1;
+
+                       if (ri->typeflags & REG_TYPE_FLT) {
+                               if (ri->typeflags & REG_SIZE_DBL) {
+                                       freefloatregs[ri->num] = 0;
+                                       freefloatregs[ri->num + 1] = 0;
+                                       ri1 = &floatregs[ri->num + 1];
+                                       list_addfirst (ri1->waitlist, ri1);
+                                       }
+                               else
+                                       freefloatregs[ri->num] = 0;
+                               }
+                       else {
+                               if (ri->typeflags & REG_SIZE_DBL) {
+                                       freeintregs[ri->num] = 0;
+                                       freeintregs[ri->num + 1] = 0;
+                                       ri1 = &intregs[ri->num + 1];
+                                       list_addfirst (ri1->waitlist, ri1);
+                                       }
+                               else
+                                       freeintregs[ri->num] = 0;
+                               }
+#endif
+                       list_addfirst (ri->waitlist, ri);
+                       }
+               }
+}
+
+
+/******************* internal function reg_suckregister ************************
+
+       searches for the first register of a list which fullfills the requirements:
+       if argument isunused is true ri->typeflags&REG_ISUNUSED has to be true too
+       if register pairs are required two adjacent register are searched
+       if a register can be found it is removed from the free list and the
+       fields 'isunused' and 'isfree' are set to false
+
+*******************************************************************************/
+
+static reginfo *reg_remove (list *l, int num) {
+       reginfo *ri;
+
+       ri = list_first (l);
+       while (ri->num != num)
+               ri = list_next (l, ri);
+       if (ri->typeflags & REG_TYPE_FLT)
+               freefloatregs[num] = 0;
+       else
+               freeintregs[num] = 0;
+       list_remove (l, ri);    
+       ri -> typeflags &= ~REG_ISFREEUNUSED;
+       return ri;
+}
+
+
+static reginfo *reg_suckregister (list *l, bool isunused)
+{
+       reginfo *ri;
+       
+       ri = list_first (l);
+
+       while (ri) {
+               if ( (!isunused) || (ri->typeflags & REG_ISUNUSED)) {
+#if (WORDSIZE == 4)
+                       reginfo *retreg = NULL;
+
+                       if (ri->typeflags & REG_SIZE_DBL) {
+                               if (ri->typeflags & REG_TYPE_FLT)
+                                       if (ri->num & 1) {
+                                               if(freefloatregs[ri->num - 1]) {
+                                                       freefloatregs[ri->num] = 0;
+                                                       retreg = reg_remove(l, ri->num - 1);
+                                                       }
+                                               }
+                                       else {
+                                               if (freefloatregs[ri->num + 1]) {
+                                                       freefloatregs[ri->num] = 0;
+                                                       retreg = ri;
+                                                       (void) reg_remove(l, ri->num + 1);
+                                                       }
+                                               }
+                               else if (freeintregs[ri->num + 1]) {
+                                               freeintregs[ri->num] = 0;
+                                               retreg = ri;
+                                               (void) reg_remove(l, ri->num + 1);
+                                               }
+                                       else if(freeintregs[ri->num - 1]) {
+                                               freeintregs[ri->num] = 0;
+                                               retreg = reg_remove(l, ri->num - 1);
+                                               }
+                               if (retreg) {
+                                       list_remove (l, ri);    
+                                       ri -> typeflags &= ~REG_ISFREEUNUSED;
+                                       return retreg;
+                                       }
+                               }
+                       else {
+                               if (ri->typeflags & REG_TYPE_FLT)
+                                       freefloatregs[ri->num] = 0;
+                               else
+                                       freeintregs[ri->num] = 0;
+                               list_remove (l, ri);    
+                               ri -> typeflags &= ~REG_ISFREEUNUSED;
+                               return ri;
+                               }
+#else
+                       list_remove (l, ri);    
+                       ri -> typeflags &= ~REG_ISFREEUNUSED;
+                       return ri;
+#endif
+                       }
+               ri = list_next (l, ri);
+               }
+       return NULL;
+}
+
+
+/******************** Funktion: reg_allocate **********************************
+
+       versucht, ein Register zu belegen, das vom richtigen Typ ist, und
+       allen gew"unschten Anforderungen entspricht.
+       
+       Parameter:
+               type .... JAVA-Grundtyp (INT,LONG,DOUBLE,FLOAT,ADDRESS)
+               saved ... Das Register soll bei Methodenaufrufen nicht zerst"ort werden
+               new ..... Das Register soll noch nie vorher verwendet worden sein
+               
+       Wenn es (aus verschiedenen Gr"unden) kein geeignetes freies Register f"ur
+       den Zweck mehr gibt, dann erzeugt diese Funktion einen Verweis auf
+       einen Platz am aktuellen Stackframe (diese Stackframe-Eintr"age erf"ullen
+       auf jeden Fall alle obigen Forderungen)
+
+*******************************************************************************/
+
+static reginfo *reg_allocate (u2 type, bool saved, bool new)
+{
+       u2 t;
+       reginfo *ri;
+
+       switch (type) {
+               case TYPE_LONG:
+                       t = REG_SIZE_DBL;
+                       break;
+               case TYPE_INT:
+                       t = 0;
+                       break;
+               case TYPE_FLOAT:
+                       t = REG_TYPE_FLT;
+                       break;
+               case TYPE_DOUBLE:
+                       t = REG_TYPE_FLT | REG_SIZE_DBL;
+                       break;
+               default:
+                       t = 0;
+               }
+
+       if (!saved) {
+               if (IS_INT_LNG_REG(t))
+                       ri = reg_suckregister (&scratchintslist, new);
+               else
+                       ri = reg_suckregister (&scratchfloatslist, new);
+               if (ri) return ri;
+               }
+
+       if (IS_INT_LNG_REG(t))
+               ri = reg_suckregister (&savedintslist, new);
+       else
+               ri = reg_suckregister (&savedfloatslist, new);
+       if (ri) return ri;
+
+       ri = DNEW (reginfo);
+       ri -> typeflags = t | REG_INMEMORY;
+#if (WORDSIZE == 4)
+       ri -> num = localvars_num;
+       if (t & REG_SIZE_DBL)
+               localvars_num += 2;
+       else
+               localvars_num++;
+#else
+       ri -> num = (localvars_num++);
+#endif
+       ri -> waitlist = (IS_INT_LNG_REG(t)) ? &savedintslist : &savedfloatslist;
+       return ri;
+}
+
+
+/********************* Funktion: reg_reallocate *******************************
+
+       versucht, ein schon einmal angefordertes (aber in der Zwischenzeit 
+       wieder freigegebenens) Register neuerlich anzufordern. 
+       Wenn das Register immer noch unbenutzt ist, dann ist alles OK 
+       (R"uckgabewert true), sonst wird 'false' zur"uckgeben, und aus der
+       neuerlichen Belegung wird nichts. 
+
+******************************************************************************/
+
+static bool reg_reallocate (reginfo *ri)
+{
+       if (!(ri->typeflags & REG_ISFREE)) return false;
+
+       ri->typeflags &= ~REG_ISFREEUNUSED;
+
+       if (ri->waitlist) list_remove (ri->waitlist, ri);
+
+       return true;
+}
+
+
+
+/****************** Funktion: reg_parlistresult *******************************
+
+       Erzeugt eine Registerreferenz auf das Register, das vom System zur
+       R"uckgabe von Werten aus Methoden verwendet wird.
+       Parameter:
+               type ... Der JAVA-Grundtyp des R"uckgabewertes
+
+******************************************************************************/
+
+static reginfo *reg_parlistresult (u2 type)
+{
+       if (type==TYPE_FLOAT || type==TYPE_DOUBLE) return &(floatregs[floatreg_ret]);
+                                                                                 else return &(intregs[intreg_ret]);
+}
+
+
+
+/*************** Funktion: reg_parlistexception ******************************
+       
+       Erzeugt eine Registerreferenz auf das Register, in dem das System die
+       Zeiger auf allf"allige Exception-Objekte bei Methodenaufrufen 
+       zur"uckliefert.
+       
+******************************************************************************/
+
+static reginfo *reg_parlistexception ()
+{
+       return &(intregs[intreg_exc]);
+}
+
+
+
+/************************ Funktion: reg_parlistpar ****************************
+
+       Erzeugt eine Registerreferenz auf ein Register, in dem das n"achste
+       Argument (in der Z"ahlung ab dem Zeitpunkt von Aufruf von 'reg_parlistinit')
+       bei Methodenaufrufen eingetragen wird. 
+       Wenn es in Summe mehr als die m"oglichen Parameter-Register werden, dann 
+       wird auch noch Platz am Stack f"ur die "uberz"ahligen Werte reserviert
+
+******************************************************************************/
+
+static int usedintpar, usedfloatpar;
+static int usedparoverflow;
+
+static reginfo *reg_parlistpar (u2 type)
+{
+       reginfo *f;
+       
+       if (type == TYPE_FLOAT || type == TYPE_DOUBLE) {
+               usedfloatpar++;
+               if (reg_parammode == PARAMMODE_NUMBERED) usedintpar++;
+               
+               if (usedfloatpar <= floatreg_argnum) {
+                       f = &floatregs[floatreg_arg1 + (usedfloatpar - 1) ];
+                       f->typeflags &= ~REG_ISUNUSED;
+                       return f;
+                       }
+               else goto overflow;
+               }
+       else {
+               usedintpar++;
+               if (reg_parammode == PARAMMODE_NUMBERED) usedfloatpar++;
+               
+               if (usedintpar <= intreg_argnum) {
+                       f = &intregs[intreg_arg1 + (usedintpar - 1) ];
+                       f->typeflags &= ~REG_ISUNUSED;
+                       return f;
+                       }
+               else goto overflow;
+       }
+
+
+
+overflow:
+       usedparoverflow++;
+       if (usedparoverflow > arguments_num) arguments_num = usedparoverflow;
+       return NULL;
+}      
+
+
+/****************** Funktion: reg_parlistinit *********************************
+
+       initialisiert die Z"ahlung der Parameter-Register
+       
+*******************************************************************************/
+
+static void reg_parlistinit()
+{
+       usedintpar = 0;
+       usedfloatpar = 0;
+       usedparoverflow = 0;
+}
+
+
+
+
+
+/***************** Funktion: reg_display *************************************
+       
+       gibt eine Register-Referenz in lesbarer Form auf 'stdout' aus.
+
+******************************************************************************/
+
+static void reg_display (reginfo *ri)
+{
+       if (ri->typeflags & REG_INMEMORY) {
+               printf ("[%d]", (int) (ri->num) );
+               }
+       else {
+               printf ("%s%d", 
+                 (IS_INT_LNG_REG(ri->typeflags)) ? "$" : "f$", 
+                 (int) (ri->num) );
+               }
+}
+
+
diff --git a/comp/regalloc.c b/comp/regalloc.c
new file mode 100644 (file)
index 0000000..be35103
--- /dev/null
@@ -0,0 +1,148 @@
+/************************** comp/regalloc.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       The register-allocator.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/03/05
+
+*******************************************************************************/
+
+
+/******************** Funktion: regalloc_doalloc ******************************
+
+       versucht f"ur ein Pseudoregister ein tats"achliches CPU-Register zu 
+       belegen.
+       Wenn noch keine Belegung stattgefunden hat, dann wird ein passendes
+       gerade freies Register angefordert.
+       Wenn das Pseudoregsiter bereits vorher schon einmal ein Belegung
+       hatte, dann wird versucht, das selbe CPU-Register wie vorher wieder
+       anzufordern. Wenn es nicht gelingt (weil es schon wieder anderwertig
+       verwendet wird), wann wird eben ein ganz neues Register angefordert.
+       
+******************************************************************************/
+
+static void regalloc_doalloc (varinfo *v)
+{
+       if (v->reg) {
+               if (! reg_reallocate (v->reg)) {
+                       v->reg = reg_allocate (v->type, v->saved, true);
+                       }
+               }
+       else {
+               v->reg = reg_allocate (v->type, v->saved, false);
+               }
+}
+
+
+
+/********************* Funktion: regalloc_activate ****************************
+
+       setzt ein Pseudoregister auf aktiv (wenn es nicht schon 
+       bereits aktiv ist), und fordert gegebenenfalls gleich ein passendes
+       CPU-Register an
+       Diese Operation wird aber nur bei Variablen mit lokalen Scope
+       gemacht.
+       
+******************************************************************************/
+
+static void regalloc_activate (varinfo *v)
+{
+       if (! v->globalscope) {
+               if (! var_isactive(v) ) {
+                       regalloc_doalloc (v);
+                       var_activate (v);
+                       }
+               }
+}
+
+
+/******************** Funktion: regalloc_deactivate ***************************
+
+       setzt ein Pseudoregister auf inaktiv (wenn es nicht schon inaktiv war)
+
+******************************************************************************/
+
+static void regalloc_deactivate (varinfo *v)
+{
+       if (! v->globalscope) {
+               if (var_isactive(v) ) {
+                       var_deactivate (v);
+                       if (v->reg) reg_free (v->reg);
+                       }
+               }
+}
+
+
+/******************** Funktion: regalloc_cmd **********************************
+
+       f"uhrt f"ur ein Pseudo-Command die Registerbelegung durch.
+       Wird von regalloc in einer Schleife aufgerufen.
+       
+******************************************************************************/ 
+       
+static void regalloc_cmd (pcmd *c)
+{
+       switch (c->tag) {
+               case TAG_DROP:
+                       regalloc_deactivate (c->dest);
+                       break;
+               case TAG_METHOD:
+                       if (c->u.method.exceptionvar) 
+                               regalloc_activate (c->u.method.exceptionvar);
+                       if (c->dest) 
+                               regalloc_activate (c->dest);
+                       break;
+               default:
+                       if (c->dest) regalloc_activate (c->dest);
+                       break;
+               }
+}
+
+
+/******************** Funktion: regalloc **************************************
+
+       f"uhrt f"ur einen ganzen Block die Registerbelegung durch.
+
+******************************************************************************/        
+
+static void regalloc (basicblock *b)
+{
+       stackinfo *tos;
+       pcmd *c;
+       varinfo *v; 
+       
+               /* alle Pseudoregister am Stack, die schon eine Belegung haben, 
+                  wieder aktivieren */
+       tos = b->stack;
+       while (tos) {
+               if (tos -> var -> reg) regalloc_activate(tos->var);
+               tos = tos->prev;
+               }
+       
+               /* alle anderen Pseudoregister am Stack belegen */
+       tos = b->stack;
+       while (tos) {
+               regalloc_activate(tos->var);
+               tos = tos->prev;
+               }
+       
+       
+               /* alle Befehle abarbeiten und Registerbelegung machen */
+       c = list_first (&b->pcmdlist);
+       while (c) {
+               regalloc_cmd (c);
+               c = list_next (&b->pcmdlist, c);                        
+               } 
+
+
+               /* alle noch aktiven Pseudoregister deaktivieren */
+       while ( (v = var_nextactive ()) != NULL) {
+               regalloc_deactivate (v);
+               }
+}
+
diff --git a/comp/stack.c b/comp/stack.c
new file mode 100644 (file)
index 0000000..a53beb2
--- /dev/null
@@ -0,0 +1,241 @@
+/***************************** alpha/gen.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       behandeln des Java-Stacks
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+static stackinfo *tos;       /* Top of Stack */
+
+
+
+/********************* Verwaltungsfunktionen *********************************/
+
+static void stack_init() { tos = NULL; }
+
+static stackinfo *stack_get () { return tos; }
+
+static void stack_restore (stackinfo *s)  { tos = s; }
+
+static bool stack_isempty () { return tos == NULL; }
+
+
+
+/********************** Funktion: stack_topslots ******************************
+
+       liefert die Anzahl der JavaVM-slots, die die oberste Pseudovariable am
+       Stack belegt (entweder 2 bei LONG und DOUBLE, oder 1 sonst)
+
+******************************************************************************/
+
+static u2 stack_topslots ()
+{
+       u2 t;
+       if (!tos) panic ("Stack is empty on attempt to determine top slots");
+
+       t = var_type (tos->var);
+       return ( (t==TYPE_LONG) || (t==TYPE_DOUBLE) ) ? 2 : 1;
+}
+
+
+/********************* Funktion: stack_push ***********************************
+
+       erzeugt eine neues Pseudoregister eines gew"unschten Typs und gibt
+       es oben auf den Stack.  
+       Ausserdem liefert die Funktion den Zeiger auf dieses Pseudoregister
+       
+******************************************************************************/
+
+static varinfo *stack_push (u2 type)
+{
+       stackinfo *s = DNEW (stackinfo);
+
+       s -> prev = tos;
+       s -> var = var_create (type);
+
+       tos = s;
+       return s -> var;
+}
+
+
+/********************** Funktion: stack_repush ********************************
+
+       Gibt ein bereits vorhandenen Pseudoregister auf den Stack
+       
+******************************************************************************/
+
+static void stack_repush (varinfo *v) 
+{
+       stackinfo *s = DNEW (stackinfo);
+
+       s -> prev = tos;
+       s -> var = v;
+
+       tos = s;
+}
+
+
+/********************** Funktion: stack_pop ***********************************
+
+       nimmt das oberste Pseudoregister vom Stack, dabei wird aber 
+       "uberpr"uft, ob der Typ stimmt.
+
+******************************************************************************/
+
+static varinfo *stack_pop (u2 type)
+{
+       varinfo *v;
+       
+       if (!tos) panic ("Stack is empty on attempt to pop");
+
+       v = tos -> var;
+       tos = tos -> prev;
+
+       if (var_type (v) != type) panic ("Popped invalid element from stack");
+       return v;
+}
+
+
+/********************* Funktion: stack_popany ********************************
+
+       nimmt das oberste Pseudoregister vom stack, ohne Typ"uberpr"ufung
+       durchzuf"uhren, wobei aber zumindest die Anzahl der notwendigen
+       Slots "ubereinstimmen muss.
+
+******************************************************************************/
+
+static varinfo *stack_popany (u2 slots)
+{
+       varinfo *v;
+       
+       if (!tos) panic ("Stack is empty on attempt to pop");
+       if (slots != stack_topslots() ) 
+               panic ("Pop would tear LONG/DOUBLE-Datatype apart");
+
+       v = tos -> var;
+       tos = tos -> prev;
+
+       return v;
+}
+
+
+
+/********************** Funktion: stack_popmany *******************************
+
+       nimmt vom Stack soviele Pseudoregister, dass die Anzahl der von
+       ihnen belegten Slots die gew"unschte Menge ergeben.
+       Zeiger auf dieses Pseudoregister werden im Array vars gespeichert, und
+       deren tats"achliche Anzahl als Funktionswert zur"uckgeliefert.
+       (Haupts"achlich f"ur die Typneutralen DUP/POP.. Operationen)
+
+******************************************************************************/
+
+static u2 stack_popmany (varid *vars, u2 slots)
+{
+       u2 ts;
+       u2 varcount=0;
+       
+       while (slots>0) {
+               ts=stack_topslots();
+               if (ts > slots) panic ("POP would tear LONG/DOUBLE-Datatype apart");
+               vars[(varcount)++] = stack_popany(ts);
+               slots -= ts;                            
+               }
+       return varcount;
+}
+
+
+/********************** Funktion: stack_pushmany ******************************
+
+       Gibt eine Anzahl von Pseudoregister auf den Stack.
+
+******************************************************************************/
+
+static void stack_repushmany (u2 varcount, varid *vars)
+{
+       u2 i;
+       for (i=0; i<varcount; i++) stack_repush(vars[(varcount-1)-i]);
+}
+
+
+/***************** Funktion: stack_addjoincode ********************************
+
+       erzeugt die passenden MOVE-Commandos, sodass alle Pseudoregisterinhalte
+       eines Stacks auf die Pseudoregister eines anderen Stacks kopiert
+       werden.
+       Dann wird der Zielstack als neuer aktueller Stack verwendet.
+       (F"ur allem f"ur Verzweigungs- und Sprungbefehle)
+       
+*******************************************************************************/ 
+
+static void stack_jointail (stackinfo *now, stackinfo *then)
+{
+       varinfo *v1,*v2;
+       u2 t;
+
+       if (now==then) return;
+       if ( (now==NULL) || (then==NULL) ) 
+               panic ("Stacks of different length on join");
+
+       v1 = now->var;
+       v2 = then->var;
+       if (v1 != v2) {
+               t = var_type (v1);
+               if (t != var_type (v2)) 
+                   panic ("Mismatching stack types on join of control flow");
+
+               pcmd_move_n_drop (t, v1,v2);
+       }
+
+       stack_jointail (now -> prev, then -> prev);
+       return;
+}
+
+static void stack_addjoincode (stackinfo *targetstack)
+{
+       stack_jointail (tos, targetstack);
+       tos = targetstack;
+}      
+
+
+/******************* Funktion: stack_makesaved ********************************
+
+       Kennzeichnet alle am Stack befindlichen Pseudoregister als
+       zu sichernde Register.
+
+*******************************************************************************/
+
+static void stack_makesaved ()
+{
+       stackinfo *s = tos;
+       while (s) {
+               var_makesaved (s->var);
+               s = s->prev;
+               }
+}
+
+
+/******************* Funktion: stack_display **********************************
+
+       Gibt den Inhalt des Stacks aus (also die Pseudoregister, die am 
+       Stack liegen)
+       (Nur zu Debug-Zwecken)
+       
+******************************************************************************/
+
+static void stack_display (stackinfo *s)
+{
+       if (s) {
+               stack_display (s->prev);
+               var_display (s->var);
+               }
+}
+
diff --git a/comp/tools.c b/comp/tools.c
new file mode 100644 (file)
index 0000000..6a9216a
--- /dev/null
@@ -0,0 +1,208 @@
+/***************************** comp/tools.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Ein paar zus"atzlich notwendige Funktionen, die sonst nirgends 
+       hinpassen.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************** Funktion: compiler_addinitclass ****************************
+
+       zum Eintragen einer Klasse in die Liste der noch zu initialisierenden 
+       Klassen
+       
+******************************************************************************/
+                                
+void compiler_addinitclass (classinfo *c)
+{
+       classinfo *cl;
+
+       if (c->initialized) return;
+       
+       cl = chain_first(uninitializedclasses);
+       if (cl == c)
+               return;
+       
+       if (cl == class)
+               cl = chain_next(uninitializedclasses);
+       for (;;) {
+               if (cl == c)
+                       return;
+               if (cl == NULL) {
+                       if (runverbose) {
+                               sprintf(logtext, "compiler_addinitclass: ");
+                               unicode_sprint(logtext+strlen(logtext), c->name);
+                               dolog();
+                               }
+                       chain_addlast(uninitializedclasses, c);
+                       return;
+                       }
+               if (c < cl) {
+                       if (runverbose) {
+                               sprintf(logtext, "compiler_addinitclass: ");
+                               unicode_sprint(logtext+strlen(logtext), c->name);
+                               dolog();
+                               }
+                       chain_addbefore(uninitializedclasses, c);
+                       return;
+                       }
+               cl = chain_next(uninitializedclasses);
+               }
+}
+                                
+
+
+/***************** Hilfsfunktionen zum Decodieren des Bytecodes ***************
+
+       lesen ein Datum des gew"unschten Typs aus dem Bytecode an der
+       angegebenen Stelle
+
+******************************************************************************/
+
+static u1 code_get_u1 (u4 pos)
+{
+       return jcode[pos];
+}
+
+static s1 code_get_s1 (u4 pos)
+{
+       return code_get_u1 (pos);
+}
+
+static u2 code_get_u2 (u4 pos)
+{
+       return ( ((u2) jcode[pos]) << 8 ) + jcode[pos+1];
+}
+
+static s2 code_get_s2 (u4 pos)
+{
+       return code_get_u2 (pos);
+}
+
+static u4 code_get_u4 (u4 pos)
+{
+       return    ( ((u4) jcode[pos])   << 24 ) 
+               + ( ((u4) jcode[pos+1]) << 16 )
+               + ( ((u4) jcode[pos+2]) << 8 )
+               + ( jcode[pos+3] );
+}
+
+static s4 code_get_s4 (u4 pos)
+{
+       return code_get_u4 (pos);
+}
+
+
+
+/******************** Funktion: descriptor2types *****************************
+
+       Decodiert einen Methoddescriptor.
+       Beim Aufruf dieser Funktion MUSS (!!!) der Descriptor ein
+       gueltiges Format haben (wird eh vorher vom loader ueberprueft).
+       
+       Die Funktion erzeugt ein Array von integers (u2), in das die 
+       Parametertypen eingetragen werden, und liefert einen Zeiger auf
+       das Array in einem Referenzparameter ('paramtypes') zur"uck.
+       Die L"ange dieses Arrays und der Methodenr"uckgabewert werden ebenfalls
+       in Referenzparametern zur"uckgeliefert.
+       
+       Der Parameter 'isstatic' gibt an (wenn true), dass kein zus"atzlicher
+       erster Eintrag f"ur den this-Zeiger in das Array eingetragen
+       werden soll (sonst wird er n"amlich automatisch erzeugt, mit dem
+       Typ TYPE_ADDRESS).
+       
+******************************************************************************/                
+
+static void descriptor2types (unicode *desc, bool isstatic,
+                 s4 *paramnum, u1 **paramtypes, s4 *returntype)
+{
+       u2 *text = desc->text;
+       s4 pos;
+       u1 *types;
+       s4 tnum;
+       
+       tnum = (isstatic) ? 0 : 1; 
+       pos=1;
+       while (text[pos] != ')') {
+          repeatcounting:      
+               
+               switch (text[pos]) {
+               case '[':  pos++;
+                          goto repeatcounting;
+               case 'L':  while (text[pos]!=';') pos++;
+                      break;
+           }
+               pos++;
+               tnum++;
+               }
+       
+       types = DMNEW (u1, tnum);
+       
+       if (isstatic) tnum=0;
+       else {
+               types[0] = TYPE_ADDRESS;
+               tnum = 1;
+               }
+       pos=1;
+       while (text[pos] != ')') {
+               switch (text[pos]) {
+               case 'B':
+               case 'C':
+               case 'I':
+               case 'S':
+               case 'Z':  types[tnum++] = TYPE_INT;
+                          break;
+               case 'J':  types[tnum++] = TYPE_LONG;
+                          break;
+               case 'F':  types[tnum++] = TYPE_FLOAT;
+                          break;
+               case 'D':  types[tnum++] = TYPE_DOUBLE;
+                          break;
+               case 'L':  types[tnum++] = TYPE_ADDRESS;
+                          while (text[pos] != ';') pos++;
+                          break;
+               case '[':  types[tnum++] = TYPE_ADDRESS;
+                          while (text[pos] == '[') pos++;
+                          if (text[pos] == 'L') while (text[pos] != ';') pos++;
+                          break;
+               default:   panic ("Ill formed methodtype-descriptor");
+               }
+               pos++;
+               }
+               
+       pos++;  /* ueberlesen von ')' */
+
+       switch (text[pos]) {
+               case 'B':
+               case 'C':
+               case 'I':
+               case 'S':
+               case 'Z':  *returntype = TYPE_INT;
+                          break;
+               case 'J':  *returntype = TYPE_LONG;
+                          break;
+               case 'F':  *returntype = TYPE_FLOAT;
+                          break;
+               case 'D':  *returntype = TYPE_DOUBLE;
+                          break;
+               case '[':
+               case 'L':  *returntype = TYPE_ADDRESS;
+                          break;
+               case 'V':  *returntype = TYPE_VOID;
+                          break;
+       
+               default:   panic ("Ill formed methodtype-descriptor");
+               }
+
+       *paramnum = tnum;
+       *paramtypes = types;
+}
+
diff --git a/comp/var.c b/comp/var.c
new file mode 100644 (file)
index 0000000..a1355a6
--- /dev/null
@@ -0,0 +1,361 @@
+/****************************** comp/var.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       verwaltet die Pseudoregister (die ich manchmal auch einfach nur
+       'Variablen'  nenne, daher der Namen des Programmteiles)
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+s4 varnum;                /* Anzahl der bereits vergebenen Variablen 
+                             (eigentlich nur, um den Variablen forlaufende
+                             Nummern zu geben, damit man sie beim Debuggen
+                             eindeutig kennzeichnen kann) */
+
+list copiedvars;          /* Liste aller Variablen die nur eine Kopie einer 
+                             anderen Variablen sind (w"ahrend der 
+                             Parse-Phase notwendig) */
+list activevars;          /* Liste aller gerade aktiven Variablen 
+                                                    (f"ur die Registerbelegungs-phase notwendig) */
+                                                     
+list vars;                /* Liste aller Variablen, die nicht in einer der
+                             obigen Listen sind */
+
+
+/********************** Funktion: var_init ************************************
+
+       initialisiert die Listen und den Variablen-Index-Z"ahler
+
+******************************************************************************/
+
+static void var_init ()
+{
+       varnum = maxlocals;
+       list_init (&vars, OFFSET (varinfo, linkage) );
+       list_init (&copiedvars, OFFSET (varinfo, linkage) );
+       list_init (&activevars, OFFSET (varinfo, linkage) );
+}
+
+
+/********************* Funktion: var_type *************************************
+
+       Liefert den JavaVM-Grundtyp einer Variablen
+
+******************************************************************************/
+
+static u2 var_type (varid v)
+{
+       return v->type;
+}
+
+
+/********************* Funktion: var_create ***********************************
+
+       Erzeugt eine neue Variable des gew"unschten Typs
+       
+******************************************************************************/
+
+static varid var_create (u2 type)
+{
+       varinfo *v = DNEW (varinfo);
+
+       list_addlast (&vars, v);
+       
+       list_init (&(v -> copies), OFFSET (varinfo, copylink) );
+       v -> original = v;
+       
+       v -> type = type;
+       v -> number = varnum++;
+       v -> active = false;
+       v -> globalscope = false;
+       v -> saved = false;
+
+       v -> reg = NULL;
+       
+       return v;
+}
+
+
+/***************** Funktion: var_createwithspecialnumber **********************
+
+       Erzeugt eine neue Variable des gew"unschten Typs, dabei wird aber als
+       Kennzeichnungsnummer eine vorgegebene Zahl verwendet (das brauche ich
+       um die lokalen Java-Variablen mit der Nummer des ihres Slots zu 
+       kennzeichnen).
+       
+******************************************************************************/
+
+static varid var_createwithspecialnumber(u2 type, u4 num)
+{
+       varinfo *v = var_create (type);
+       varnum--;
+       v -> number = num;
+       return v;
+}
+
+
+/*************** Funktion: var_makesaved **************************************
+
+       Kennzeichnet eine Variable daf"ur, dass sie bei Methodenaufrufen nicht
+       zerst"ort werden darf.
+       
+******************************************************************************/
+
+static void var_makesaved (varid v)
+{
+       v -> saved = true;
+       v -> reg = NULL;
+}
+
+
+/*************** Funktion: var_proposereg *************************************
+
+       Macht dem Regiserallokator einen Vorschlag, mit welchem Register
+       eine Variable belegt werden sollte (bei Methodenaufrufen k"onnen so
+       viele Umlade-Befehle in die Argumentregister vermieden werden).
+       Aber: Die Anforderung, dass ein Register gesichert sein soll, hat auf
+               jeden Fall Priorit"at "uber so einen Vorschlag.
+       
+******************************************************************************/
+
+static void var_proposereg (varid v, reginfo *r)
+{
+       if (v -> saved) return;
+       
+       v -> reg = r;
+}
+
+
+/******************** Funktion: var_makecopy **********************************
+
+       kennzeichnet eine Variable daf"ur, dass sie nur eine Kopie einer anderen
+       Variable enth"alt. 
+
+******************************************************************************/
+
+static void var_makecopy (varid original, varid copy)
+{
+       list_addlast (&(original->copies), copy);
+       copy -> original = original;
+       
+       list_remove (&vars, copy);
+       list_addlast (&copiedvars, copy);
+}
+
+
+/******************** Funktion: var_unlinkcopy ********************************
+
+       eine Variable, die bis jetzt in der Liste der Kopien eingetragen
+       war, wird wieder auf normalen Zustand gebracht.
+       
+******************************************************************************/
+
+static void var_unlinkcopy (varid copy)
+{
+       list_remove (&(copy->original->copies), copy);
+       copy -> original = copy;
+       
+       list_remove (&copiedvars, copy);
+       list_addlast (&vars, copy);
+}
+
+
+/******************* Funktion: var_isoriginal *********************************
+
+       Liefert true, wenn die Variable selber das Original ist, und keine
+       Kopie einer anderen Variablen (das heisst, wenn sie nicht in der Liste
+       der Kopien eingetragen ist)
+       
+******************************************************************************/
+
+static bool var_isoriginal (varid copy)
+{
+       return (copy -> original == copy) ? true : false;
+}
+
+
+/******************* Funktion: var_findoriginal *******************************
+
+       Sucht zu einer Variablen das Original (wenn die Variable eine Kopie ist),
+       oder gibt die Variable selbst zur"uck (im anderen Fall).
+       
+******************************************************************************/
+
+static varid var_findoriginal (varid v)
+{
+       return v->original;
+}
+
+
+/******************* Funktion: var_nextcopy ***********************************
+
+       Gibt die erste noch eingetragene Kopie einer Variablen zur"uck.
+       (oder NILL, wenn die Variable keine Kopien hat)
+       
+******************************************************************************/
+
+static varid var_nextcopy (varid original) 
+{
+       return list_first (&original->copies);
+}
+
+
+/******************* Funktion: var_nextcopiedvar ******************************
+
+       Gibt die erste "uberhaupt noch vorhandene Variable zu"uck, die eine
+       Kopie irgendeiner anderen Variablen ist.
+       
+******************************************************************************/
+
+static varid var_nextcopiedvar ()
+{
+       return list_first (&copiedvars);
+}
+
+
+
+/*********************** Funktion: var_isactive *******************************
+
+       Lieftert true, wenn die Variable gerade aktiviert ist (d.h., wenn 
+       irgendwann vorher 'var_activate' aufgerufen wurde) 
+
+******************************************************************************/
+
+static bool var_isactive (varinfo *v)
+{
+       return v->active;
+}
+
+
+/******************** Funktion: var_activate **********************************
+
+       Aktiviert eine Variable, d.h. sie wird in die Liste der aktiven
+       Variablen eingetragen.
+       
+******************************************************************************/
+       
+static void var_activate (varinfo *v)
+{
+       list_remove (&vars, v);
+       list_addlast (&activevars, v);  
+       v -> active = true;
+}
+
+
+/******************** Funktion: var_deactivate ********************************
+
+       Deaktiviert eine Variable (Gegenst"uck zu var_activate)
+       
+******************************************************************************/
+
+static void var_deactivate (varinfo *v)
+{
+       list_remove (&activevars, v);
+       list_addlast (&vars, v);
+       v -> active = false;
+}
+
+
+/****************** Funktion: var_nextactive **********************************
+
+       Liefert die erste noch aktivierte Variable 
+
+******************************************************************************/
+
+static varinfo *var_nextactive ()
+{
+       return list_first (&activevars);
+}
+
+
+
+/**************************** Funktion: var_display **************************
+
+       Gibt eine abdruckbare Darstellung einer Variablen aus.
+       (nur zu Debug-Zwecken)
+       
+*****************************************************************************/
+
+static void var_display (varinfo *v)
+{
+       if (v==NOVAR) {
+               printf ("_ ");
+               return;
+               }
+               
+       switch (v->type) {
+       case TYPE_INT: printf ("I"); break;
+       case TYPE_LONG: printf ("L"); break;
+       case TYPE_FLOAT: printf ("F"); break;
+       case TYPE_DOUBLE: printf ("D"); break;
+       case TYPE_ADDRESS: printf ("A"); break;
+       default: printf ("?");
+       }
+       printf ("%d", v->number);
+
+       if (v->reg) {
+               printf ("(="); 
+               reg_display (v->reg);
+               printf (")");
+               }
+       printf (" ");
+}
+
+
+/************************ Funktion: var_displayall **************************
+
+       Gibt eine abdruckbare Darstellung aller Variablen aus.
+       (nur zu Debug-Zwecken)
+       
+*****************************************************************************/
+
+void var_displayall ()
+{
+       varid v;
+       int num=0;
+       varid *sorted = DMNEW (varid, varnum);
+
+       printf ("\n   Types of all pseudo-variables:\n");
+       
+       for (num=0; num<varnum; num++) sorted[num] = NULL;
+       v = list_first (&vars);
+       while (v) {
+               if (sorted[v->number]) {
+                       printf ("  Local variable overlay:  "); 
+                       if (v->saved) printf ("* ");
+                              else   printf ("  ");
+                       
+                       var_display (v);
+                       printf ("\n");
+                       } 
+               else sorted[v->number] = v;
+               
+               v = list_next (&vars, v);
+               }
+
+       
+       for (num=0; num<varnum; num++) {
+               v = sorted[num];
+               if (v) {
+                       if (v->saved) printf ("* ");
+                              else   printf ("  ");
+
+                       var_display (v);
+                       if (!v->reg) printf ("   ");
+                       
+                       if ( (num%5) == 4 ) printf ("\n");
+                       else printf ("\t");
+                       }
+               }
+       
+       printf ("\n");
+}
+
+
diff --git a/compiler.c b/compiler.c
new file mode 100644 (file)
index 0000000..18f0949
--- /dev/null
@@ -0,0 +1,429 @@
+/****************************** compiler.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt die Funktionen mit denen die JavaVM - Methoden in Maschinencode
+       "ubersetzt werden.
+       Ein Aufruf vom compiler_compile "ubersetzt genau eine Methode.
+       Alle in diesem Modul global definierten Variablen gelten nur f"ur 
+       eben diese gerade in der "Ubersetzung befindlichen Methode.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/22
+
+*******************************************************************************/
+
+#include "global.h"
+#include "compiler.h"
+
+#include "loader.h"
+#include "tables.h"
+#include "builtin.h"
+#include "native.h"
+#include "asmpart.h"
+
+#include "threads/thread.h"              /* schani */
+
+
+/*************************** globale Schalter ********************************/
+
+extern int newcompiler;                
+methodptr new_compile (methodinfo *m);  /* compile a method with new compiler */
+
+/**************************  no all in newcomp.c
+
+bool compileverbose = false;
+bool showstack = false;
+bool showintermediate = false;
+bool showdisassemble = false; 
+int  optimizelevel = 0;
+
+bool checkbounds = true;
+bool checknull = true;
+bool checkfloats = true;
+bool checksync = true;
+
+bool getcompilingtime = false;
+long int compilingtime = 0;
+int  has_ext_instr_set = 0;
+
+bool statistics = false;         
+
+int count_jit_calls = 0;
+int count_methods = 0;
+int count_spills = 0;
+int count_pcmd_activ = 0;
+int count_pcmd_drop = 0;
+int count_pcmd_zero = 0;
+int count_pcmd_const_store = 0;
+int count_pcmd_const_alu = 0;
+int count_pcmd_const_bra = 0;
+int count_pcmd_load = 0;
+int count_pcmd_move = 0;
+int count_pcmd_store = 0;
+int count_pcmd_store_comb = 0;
+int count_pcmd_op = 0;
+int count_pcmd_mem = 0;
+int count_pcmd_met = 0;
+int count_pcmd_bra = 0;
+int count_pcmd_table = 0;
+int count_pcmd_return = 0;
+int count_pcmd_returnx = 0;
+int count_check_null = 0;
+int count_javainstr = 0;
+int count_javacodesize = 0;
+int count_javaexcsize = 0;
+int count_calls = 0;
+int count_tryblocks = 0;
+int count_code_len = 0;
+int count_data_len = 0;
+int count_cstub_len = 0;
+int count_nstub_len = 0;
+
+********************/
+
+
+/************************ die Datentypen f"ur den Compiler *******************/ 
+
+#include "comp/defines.c"
+
+
+
+/******************* globale Variablen fuer den Compiler *********************/
+
+static methodinfo *method;      /* Zeiger auf die Methodenstruktur */
+static unicode   *descriptor;   /* Typbeschreibung der Methode */
+static classinfo *class;        /* Klasse, in der die Methode steht */
+       
+static s4 maxstack;             /* maximale Gr"osse des JavaVM-Stacks */
+static s4 maxlocals;            /* maximale Anzahl der JavaVM-Variablen */
+static u4 jcodelength;          /* L"ange des JavaVM-Codes */
+static u1 *jcode;               /* Zeiger auf den JavaVM-Code */
+static s4 exceptiontablelength; /* L"ange der Exceptiontable */
+static exceptiontable *extable; /* Zeiger auf die Exceptiontable */
+
+
+static list reachedblocks;      /* Die Listenstruktur f"ur alle vom Parser 
+                                   bereits irgendwie erreichten Bl"ocke */
+static list finishedblocks;     /* Die Listenstruktur f"ur alle Bl"ocke, die
+                                   vom Parser bereits durchgearbeitet wurden */
+
+static basicblock **blocks;     /* Eine Tabelle, so lang wie der JavaVM-Code, */
+                                /* in der an jeder Stelle, an der ein */
+                                /* Basicblock beginnt, der Zeiger auf die */
+                                /* ensprechende Basicblock-Struktur einge- */
+                                /* tragen ist. */
+
+static bool isleafmethod;       /* true, wenn die Methode KEINE weiteren 
+                                   Unterprogramme mehr aufruft */
+
+static s4        mparamnum;     /* Die Anzahl der Parameter (incl. this) */
+static u1       *mparamtypes;   /* Die Typen aller Parameter (TYPE_INT,...) */
+static s4        mreturntype;   /* R"uckgabewert der Methode */
+static varinfo **mparamvars;    /* Die PCMD-Variablen, die die Parameter */
+                                /*   zu Methodenstart enthalten sollen */
+
+
+static chain *uninitializedclasses;  
+                                /* Eine Tabelle aller von der Methode */
+                                /* irgendwie ben"otigten Klassen, die */
+                                /* vor dem Start der Methode initialisiert */
+                                /* werden m"ussen (wenn sie es noch nicht */
+                                /* sind) */
+                                
+
+/************************ Subsysteme des Compilers ***************************/
+
+
+#include "comp/tools.c"    /* ein paar n"utzliche Hilfsfunktionen */
+#include "comp/mcode.c"    /* systemUNabh"angiger Teil des Codegenerators */
+
+#include "comp/reg.c"      /* Registerverwaltung */
+#include "comp/var.c"      /* Die Verwaltung der PCMD-Variblen */
+#include "comp/pcmd.c"     /* Funktionen f"ur die Pseudocommandos (=PCMD) */
+#include "comp/local.c"    /* Verwaltung der lokalen JavaVM-Variablen */
+#include "comp/stack.c"    /* Verwaltung des JavaVM-Stacks */
+#include "comp/regalloc.c" /* Registerallokator */
+
+#include "sysdep/gen.c"    /* systemABh"angiger Codegenerator */
+#include "sysdep/disass.c" /* Disassembler (nur zu Debug-Zwecken) */ 
+
+#include "comp/block.c"    /* Verwaltung der basic blocks */ 
+#include "comp/parse.c"    /* JavaVM - parser */
+
+
+
+
+/****** Die Dummy-Function (wird verwendet, wenn kein Code vorhanden ist) ****/
+
+static void* do_nothing_function() 
+{
+       return NULL;
+}
+
+
+
+
+/******************************************************************************/
+/*********************** eine Methode compilieren *****************************/
+/******************************************************************************/
+
+
+methodptr compiler_compile (methodinfo *m)
+{
+       u4 i;
+       basicblock *b;
+       long int starttime=0,stoptime=0;
+       long int dumpsize;
+       
+       if (newcompiler) {
+               return new_compile(m);
+               }
+
+       /*** Wenn schon ein Maschinencode vorliegt, dann sofort beenden ****/
+
+       count_jit_calls++;             /* andi   */
+       if (m->entrypoint) return m->entrypoint;
+
+       intsDisable();                 /* schani */
+       
+
+       /**************** Marke fuer den DUMP-Speicher aufheben *****************/
+
+       dumpsize = dump_size ();
+
+
+       /**************** Zeit messen *******************************************/
+
+       count_methods++;             /* andi   */
+       if (getcompilingtime) starttime=getcputime();
+
+       /*** Meldung ausgeben. Wenn kein JavaVM-Code vorhanden ist, beenden ****/
+
+       if (m->jcode) {
+               if (compileverbose) {
+                       sprintf (logtext, "Compiling: ");
+                       unicode_sprint (logtext+strlen(logtext), m->class->name);
+                       strcpy (logtext+strlen(logtext), ".");
+                       unicode_sprint (logtext+strlen(logtext), m->name);
+                       unicode_sprint (logtext+strlen(logtext), m->descriptor);
+                       dolog ();
+                       }
+               }
+       else {
+               sprintf (logtext, "No code given for: ");
+               unicode_sprint (logtext+strlen(logtext), m->class->name);
+               strcpy (logtext+strlen(logtext), ".");
+               unicode_sprint (logtext+strlen(logtext), m->name);
+               unicode_sprint (logtext+strlen(logtext), m->descriptor);
+               dolog ();
+               intsRestore();           /* schani */
+               return (methodptr) do_nothing_function;
+               }
+
+
+       /*********** Initialisieren der Variablen und Subsysteme *****************/
+
+       isleafmethod = true;              /* bis sich das Gegenteil herausstellt */
+
+       method = m;
+       descriptor = m->descriptor;
+       class = m->class;
+       
+       maxstack = m->maxstack;
+       maxlocals = m->maxlocals;
+       jcodelength = m->jcodelength;
+       jcode = m->jcode;
+       count_tryblocks += (exceptiontablelength = m->exceptiontablelength);
+       extable = m->exceptiontable;
+
+#ifdef STATISTICS
+       count_javacodesize += jcodelength + 18;
+       count_javaexcsize += exceptiontablelength * 8;
+#endif
+
+       list_init (&reachedblocks,   OFFSET(basicblock, linkage) );
+       list_init (&finishedblocks,  OFFSET(basicblock, linkage) );
+
+       blocks = DMNEW (basicblock*, jcodelength);
+       for (i=0; i<jcodelength; i++) blocks[i] = NULL;
+
+
+       descriptor2types (descriptor, (m->flags & ACC_STATIC) != 0,
+                         &mparamnum, &mparamtypes, &mreturntype);
+       m->paramcount = mparamnum;
+       m->returntype = mreturntype;
+       mparamvars = DMNEW (varid, mparamnum);
+
+       reg_init ();
+       mcode_init ();
+       var_init();
+       local_init();
+
+       uninitializedclasses = chain_new(); 
+               /* aktuelle Klasse zur Liste der m"oglicherweise zu 
+                  initialisierenden Klassen dazugeben */
+       compiler_addinitclass (m->class);
+
+
+       /************************ Compilieren  ************************/
+       
+            /* Fuer jedes Sprungziel einen eigenen Block erzeugen */
+       block_firstscann ();
+
+                       /* Den ersten Block als erreicht markieren, der Stack ist leer */
+       stack_init();
+       subroutine_set(NULL);
+       block_reach ( block_find(0) );
+       
+                       /* Alle schon erreichten Bl"ocke durchgehen und fertig machen */
+       while ( (b = list_first (&reachedblocks)) ) {
+               list_remove (&reachedblocks, b);
+               list_addlast (&finishedblocks, b);
+               b -> finished = true;
+
+               pcmd_init ( &(b->pcmdlist) );
+               parse (b);
+               }
+       
+       input_args_prealloc ();
+
+                       /* F"ur alle Bl"ocke die Registerbelegung durchfuehren */
+       b = list_first (&finishedblocks);
+       while (b) {
+               regalloc (b);
+               b = list_next (&finishedblocks, b);
+               }
+
+
+                   /* Registerbelegung fuer die lokalen JAVA-Variablen */
+       local_regalloc ();
+
+       
+
+       
+       /**************** Maschinencode generieren **********************/
+
+       gen_computestackframe ();
+       gen_header ();
+
+
+       for (i=0; i<jcodelength; i++) {
+               b = blocks[i];
+               if (b) if (b->reached) block_genmcode (b);
+               }
+       
+       b = list_first (&finishedblocks);
+       while (b) {
+               if (b->type != BLOCKTYPE_JAVA) block_genmcode (b);
+               b = list_next (&finishedblocks, b);
+               }
+
+       
+       mcode_finish ();
+
+       
+       /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
+               
+       if (showintermediate) {
+               printf ("Leaf-method: %s\n", isleafmethod ? "YES":"NO");
+               printf ("Parameters: ");
+               for (i=0; i<mparamnum; i++) var_display (mparamvars[i]);
+               printf ("\n");
+               printf ("Max locals: %d\n", (int) maxlocals);
+               printf ("Max stack:  %d\n", (int) maxstack);
+
+               for (i=0; i<jcodelength; i++) {
+                       b = blocks[i];
+                       if (b) if (b->reached) block_display (b);
+                       }
+               b = list_first (&finishedblocks);
+               while (b) {
+                       if (b->type != BLOCKTYPE_JAVA) block_display (b);
+                       b = list_next (&finishedblocks, b);
+                       }
+                       
+               var_displayall();
+               fflush (stdout);
+               }
+
+       if (showdisassemble) {
+               dseg_display ();
+               disassemble ( (void*) (m->mcode + dseglen), mcodelen);
+               fflush (stdout);
+               }
+
+
+
+       /***************** Dump-Speicher zurueckgeben *************/
+
+       dump_release (dumpsize);
+
+
+       /******************* Zeit messen **************************/
+       
+       if (getcompilingtime) {
+               stoptime = getcputime();
+               compilingtime += (stoptime-starttime); 
+               }
+
+       /******** Alle Klassen initialisieren, die gebraucht wurden *******/
+
+       {
+               chain *u = uninitializedclasses;    /* wegen reentrant-F"ahigkeit */ 
+               classinfo *c;                       /* d"urfen ab hier keine */
+                                                   /* globalen Variablen verwendet */
+               while ( (c = chain_first(u)) ) {    /* werden */
+                       chain_remove (u);
+                       
+                       class_init (c);                         /* ruft unter Umst"anden wieder */
+                                                       /* den Compiler auf */
+                       }
+               chain_free (u);
+       }
+
+       intsRestore();                   /* schani */
+
+
+
+       /****** Return pointer to the methods entry point **********/
+               
+       return m -> entrypoint;
+
+}
+
+
+
+/***************** Funktionen zum Initialisieren und Terminieren *************/
+
+void compiler_init ()
+{
+       u4 i;
+
+       has_ext_instr_set = ! has_no_x_instr_set();
+
+       for (i=0; i<256;i++) stdopdescriptors[i]=NULL;
+
+       for (i=0; i<sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
+               
+               if (stdopdescriptortable[i].isfloat && checkfloats) {
+                       stdopdescriptortable[i].supported = false;
+                       }
+
+               stdopdescriptors[stdopdescriptortable[i].opcode] = 
+                  &(stdopdescriptortable[i]);
+               }
+}
+
+
+void compiler_close()
+{
+       reg_close ();
+       mcode_close();
+}
+
diff --git a/compiler.h b/compiler.h
new file mode 100644 (file)
index 0000000..c9e0e4a
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************** compiler.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (PCMDs).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/22
+
+*******************************************************************************/
+
+/************** Compiler-switches (werden von main gesetzt) *****************/
+
+
+extern bool compileverbose;     
+extern bool showstack;          
+extern bool showdisassemble;    
+extern bool showintermediate;   
+extern int   optimizelevel;      
+
+extern bool checkbounds;        
+extern bool checknull;          
+extern bool checkfloats;        
+extern bool checksync;          
+
+extern int  has_ext_instr_set;  
+
+extern bool getcompilingtime;   
+extern long int compilingtime;  
+
+extern bool statistics;         
+
+extern int count_jit_calls;
+extern int count_methods;
+extern int count_spills;
+extern int count_pcmd_activ;
+extern int count_pcmd_drop;
+extern int count_pcmd_zero;
+extern int count_pcmd_const_store;
+extern int count_pcmd_const_alu;
+extern int count_pcmd_const_bra;
+extern int count_pcmd_load;
+extern int count_pcmd_move;
+extern int count_pcmd_store;
+extern int count_pcmd_store_comb;
+extern int count_pcmd_op;
+extern int count_pcmd_mem;
+extern int count_pcmd_met;
+extern int count_pcmd_bra;
+extern int count_pcmd_table;
+extern int count_pcmd_return;
+extern int count_pcmd_returnx;
+extern int count_check_null;
+extern int count_check_bound;
+extern int count_javainstr;
+extern int count_javacodesize;
+extern int count_javaexcsize;
+extern int count_calls;
+extern int count_tryblocks;
+extern int count_code_len;
+extern int count_data_len;
+extern int count_cstub_len;
+extern int count_nstub_len;
+
+
+/******************************* Prototypes *********************************/
+
+methodptr compiler_compile (methodinfo *m);
+
+void compiler_init ();
+void compiler_close ();
+
+u1 *createcompilerstub (methodinfo *m);
+u1 *createnativestub (functionptr f, methodinfo *m);
+u1 *ncreatenativestub (functionptr f, methodinfo *m);
+
+void removecompilerstub (u1 *stub);
+void removenativestub (u1 *stub);
+
diff --git a/doc/collect.doc b/doc/collect.doc
new file mode 100644 (file)
index 0000000..b71a0f9
--- /dev/null
@@ -0,0 +1,212 @@
+/*************************** doc/collect.doc ***********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt die Beschreibung des Garbage Collectors
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+Generell:
+
+F"ur den CACAO habe ich einen recht einfachen Mark and Sweep - Collector
+implementiert, mit dem der Speicher immer dann ges"aubert wird, wenn
+eine Anforderung nicht zufriedenstellend durchgef"uhrt werden
+kann (im Klartext: der GC l"auft NICHT in einem eigenen Thread).
+
+Der Heap ist ein einziger Speicherblock, der gleich zu Programmstart
+angelegt wird, und dessen Gr"osse sich nicht mehr "andern kann.
+(also immer gleich gen"ugend Speicher anlegen! Bei Maschinen mit 
+virtuellem Speicher sollte das kein Problem sein)
+
+Der Collector verschiebt keine Objekte im Speicher, und er kommt mit
+minimaler Information "uber die innere Struktur der Objekte aus
+(um es pr"aziser zu sagen: Der GC nimmt bei allen Daten einmal an,
+dass es sich dabei um Zeiger auf Objekte in den Heap handelt. Wenn
+irgendwelche Zahlen z"uf"allig einen g"ultigen Zeiger auf ein Objekt
+darstellen, dann wird dieses Objekt eben nicht freigeben.)
+
+Der Heap ist in kleine unteilbare Einheiten aufgeteilt, die nur immer
+als ganzen vergeben werden k"onnen (Heap-Bl"ocke), deren Gr"osse
+auf jeden Fall die in Java n"otigen Alignment-Bedingungen erf"ullt.
+
+
+Notwendige zus"atzliche Datenstrukturen
+---------------------------------------
+
+Der GC muss auf jeden Fall wissen, wo im Heap g"ultige Objekte stehen
+(damit die Markierung mit m"oglicher- (aber nicht notwendigerweise) 
+g"ultigen Zeigern richtig funktioniert).
+
+Dazu verwaltet er ein Bitfeld ('startbits'), in dem f"ur jeden Heap-Block
+eintr"agt, ob an der Stelle ein Objekt anf"angt. Zu"atzlich werden auch
+alle FREIEN Speicherbereiche mit so einem Bit markiert.
+
+Ein zweites Bitfeld ('referencebits') gibt an, ob in dem Objekt, das 
+an der Stelle anf"angt, noch weitere Referenzen auf andere Objekte 
+gespeichert sein k"onnen.
+(Damit die Markierungsphase fr"uhzeitig abgebrochen werden kann)
+
+Beispiel:
+
+Heap:          | Obj1 |  Obj2 |     frei     | Obj3 | Obj3 |  frei   |
+               -------------------------------------------------------
+
+startbits:     100000010000000100000000000000100000010000001000000000
+
+referencebits: 100000000000000000000000000000100000000000000000000000
+
+
+(in obigem Beispiel k"onnten Obj1 und Obj3 noch weitere Referenzen
+enthalten)
+
+Man beachte: Die Bitfelder werden nur soweit benutzt, als tats"achlich 
+schon Platz am Heap vergeben worden ist (wird mit Hilfe einer globalen
+Variable 'topofheap' gehandhabt). Alle dar"uberhausgehenden Bits sind
+noch 0. Das letzte Objekte im Heap (oder der freie Speicherbereich)
+wird also nicht mit so einem 1-Bit abgeschlossen.
+
+
+Vorgangsweise beim Anlegen eines neuen Objektes
+-----------------------------------------------
+
+In einer Freispeicherliste sind alle freien Bereiche eingetragen 
+(die Freispeicherlisten verwenden dabei gleich den freien Speicher 
+f"ur die notwendige Verkettung).
+Zuerst muss beliebiger passender Bereich gesucht werden.
+
+1. Fall: Bereich hat genau die richtige Gr"osse
+       - Aus der Freispeicherliste austragen
+       - gegebenenfalls das zugeh"orige Bit im Feld 'referencebits' 
+         setzen
+       - fertig
+       
+2. Fall: Bereich ist gr"osser als notwendig
+       - Aus der Freispeicherliste austragen.
+       - In Liste das Restst"uckchen eintragen
+       - Ein Bit im Bitfeld 'startbits' eintragen, wo der neue freie 
+         Speicher anf"angt.
+       - gegebenenfalls das dem neuen Objete zugeh"orige Bit im Feld 
+      'referencebits' setzen
+       - fertig
+       
+3. Fall: Es ist kein freier Bereich mehr in der Freispeicherliste
+       - das neue Objekte wird ganz oben am Heap angelegt
+       - Bit im Bitfeld 'startbits' am der Stelle 'topofheap' eintragen.
+       - den 'topofheap'-Z"ahler im die Objektel"ange erh"ohen 
+       - eventuell ein Bit in 'referencebits' setzen
+       - fertig
+       
+4. Fall: Es ist zuwenig Speicher mehr oben im Heap "ubrig
+       - Garbage Collection durchf"uhren
+       - alles nocheinmal probieren
+       
+
+Vorgangsweise zur Garbage Collection
+------------------------------------
+
+Ein drittes Bitfeld ('markbits') wird ben"otigt, das zuerst mit
+0 initialisiert wird.
+
+In der Markierungsphase werden alle Objekte durchgegangen, die
+von irgendwo im Stack oder von globalen Variablen aus erreichbar
+sind.
+Ein Zeiger zeigt tats"achlich auf ein g"ultiges Objekt im Heap, wenn:
+       - Der Zeiger in den Bereich des Heap zeigt
+       - Der Zeiger richtiges Alignment hat (auf Blockgr"osse)
+       - Das zugeh"orige Bit in 'startbits' gesetzt ist
+
+Wenn das der Fall ist, und das Bit in 'markbits' noch nicht gesetzt ist,
+dann wird dieses Bit jetzt gesetzt, und wenn noch dazu das Bit in
+'referencebits' gesetzt ist, dann werden alle Referenzen vom Objekt
+rekuriv ebenfalls markiert.
+Die L"ange des Objektes erf"ahrt man aus dem 'startbits'-Feld. Man muss
+nur den n"achsten 1er suchen (oder vorher abbrechen, wenn man die
+Stelle 'topofheap' erreicht).
+
+
+Beispiel:
+
+Heap:          | Obj1 |  Obj2 |     frei     | Obj3 | Obj4 |  frei   |
+               -------------------------------------------------------
+
+startbits:     100000010000000100000000000000100000010000001000000000
+markbits:      000000010000000000000000000000100000010000000000000000
+
+referencebits: 100000000000000000000000000000100000000000000000000000
+
+In dem Beispiel wurden nur mehr Obj2 und Obj3 als erreichbar erkannt,
+die anderen Objekte wurden nicht erreicht. 
+
+Anmerkung: Es k"onnte hier passieren, dass ein freier Speicherbereich 
+       irrt"umlich als Objekte markiert und f"ur den folgenden
+       Sweep-Durchlauf blockiert wird. Das sollte aber nur SEHR selten 
+       vorkommen.
+
+
+Nach der Markierungsphase sieht man schon, dass einige Objekte
+weggeworfen werden sollen. Damit die zu diesen Objekte geh"orenden
+'referencebits' ebenfalls gel"oscht werden, braucht man nur
+ein logisches UND der beiden Bitfelder 'markbits' und 'referencebits'
+durchf"uhren, und das Ergebnis in 'referencebits' speichern.
+
+Obiges Beispiel:
+
+markbits:      000000010000000000000000000000100000010000000000000000
+referencebits: 100000000000000000000000000000100000000000000000000000
+---------------------------------------------------------------------
+         UND   000000000000000000000000000000100000000000000000000000  
+         
+
+
+
+
+F"ur die Sweep-Phase wird der gesammte Bereich linear durchgegangen,
+und alle freien Bereiche in die Freispeicherliste eingeh"angt.
+
+Dazu wird der Anfang des ersten freien Bereiches gesucht, und zwar indem
+nach der erste Stelle gesucht wird, an der ein startbit GESETZT ist,
+aber das markbit NICHT gesetzt ist.
+Das Ende des freien Bereiches findet man dort, wo das n"achste
+markbit GESETZT ist.
+(dabei werden auch automatisch hintereinanderliegenden Speicherst"ucke
+zusammengefasst)
+Den gesammten Bereich kann man jetzt in die Freispeicherliste einh"angen,
+und gleichzeitig muss noch ds markbit, an dem der Bereich anf"angt,
+gesetzt werden (wozu, das wird weiter unten erkl"art)
+
+F"ur alle folgenden Bl"ocke geht man genauso vor, bis das Ende des
+Heaps erreicht ist.
+Die oben erw"ahnten Bit-Suche-Operationen gehen - wenn man sie gut
+implementiert - relativ rasch (z.B. mit 64-Bit-Operationen auf einer
+DEC-Alpha).
+
+
+Der Grund, warum man alle freien Bereiche mit einem zus"atzlichen
+Markierungsbit versieht ist der, dass jetzt zu Ende des Sweep in
+'markbits' genau diejenige Bits stehen, die eigentlich auch in 
+'startbits' geh"oren, n"amlich eine Kennzeichnung aller lebenden
+Objekte und aller Freispeicherbereiche.
+
+
+Fortsetzung des obigen Beispiels:
+
+Heap:          | frei |  Obj2 |     frei     | Obj3 |  frei          |
+               -------------------------------------------------------
+
+startbits:     100000010000000100000000000000100000010000001000000000
+markbits:      100000010000000100000000000000100000010000000000000000
+
+referencebits: 000000000000000000000000000000100000000000000000000000
+
+
+Durch einfaches Umkopieren der 'markbits' auf die 'startbits' 
+(oder noch besser: durch Austauschen der beiden Zeiger) ist der
+Garbage-Collection-Durchlauf abgeschlossen.
+
+
diff --git a/doc/gen.doc b/doc/gen.doc
new file mode 100644 (file)
index 0000000..a0f9b4e
--- /dev/null
@@ -0,0 +1,602 @@
+/***************************** doc/gen.doc *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt die Beschreibung der Schnittstelle zwischen dem systemUNabh"angigen
+       und dem systemABh"angigen Teil des Compilers.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/03/05
+
+*******************************************************************************/
+
+Der gr"osste Teil des Compilers ist maschinenunabh"angig programmiert,
+aber diejenigen Programmteile, die den tats"achlichen Maschinencode
+erzeugen, m"ussen f"ur jede Maschine extra implementiert werden.
+
+Alle diese abh"angigen Teile habe ich im Verzeichnis 'sysdep' zusammen-
+gefa"sst (und sysdep selbst ist ein symbolischer Link auf das entsprechende
+Verzeichnis der tats"achlichen Architektur, so dass nur mehr dieser Link
+umgesetzt werden muss, damit das Programm auf einem anderen Rechner
+compiliert werden kann).
+
+Im Verzeichnis 'comp' gibt es folgende systemabh"angige Programmteile:
+(diese Dateien sind als Links in das Verzeichnis 'sysdep' realisiert)
+
+       reg.c ..... Registerbelegung
+       gen.c ..... generieren von Maschinencode
+       disass.c .. Disassembler (nur f"ur Debug-Zwecke)
+       
+
+-------------------------------------------------------------------------------
+1. Der Registerallokator  (reg.c)
+-------------------------------------------------------------------------------
+
+Die Pseudoregister, die vom Compiler bei allen Operationen verwendet werden,
+m"ussen irgendwann mit tats"achlichen CPU-Registern belegt werden.
+
+Die Belegung funktioniert nach folgendem Prinzip:
+       
+Immer, wenn der Compiler ein CPU-Register f"ur eines seiner
+Pseudoregister ben"otigt, ruft er eine entsprechende Funktion des
+Allokators auf. Diese erzeugt eine 'reginfo'-Struktur, die die 
+Information f"ur ein Register enth"alt (Typ INT/FLOAT, Registernummer,
+Auslagerungsinformation...).
+Der Inhalt der 'reginfo'-Struktur ist f"ur den systemunabh"angigen
+Compiler nicht von Bedeutung (wird also sozusagen als opaker Datentyp
+behandelt).
+Wenn irgendwann nicht mehr genug CPU-Register zur Verf"ugung stehen,
+dann darf der Allokator Register auch in den Speicher (also auf den
+Stack) auslagern. Er muss dazu einfach eine entsprechende 'reginfo'-
+Struktur erzeugen, die dann eben den Offset im Stackframe und
+alle n"otigen Zusatzinformationen enth"alt.
+
+       
+Die Funktionen im einzelnen sind:
+
+void reg_init ()
+       initialisiert den Registerallokator
+
+       
+reginfo *reg_allocate(u2 type, bool saved, bool new)
+       erzeugt eine reginfo-Struktur mit den entsprechenden Eintr"agen.
+       (Diese Datenstruktur muss am DUMP-Speicher [siehe Toolbox-Beschreibung]
+       angelegt werden, damit sie irgendwann sp"ater automatisch freigegeben
+       wird)
+
+       Das so belegte Register muss verschiedene Voraussetzugen erf"ullen:
+       - Es muss ein Datum vom Java-Typ type 
+         (= TYPE_INT/TYPE_LONG/TYPE_FLOAT/TYPE_DOUBLE/TYPE_ADDRESS) 
+         aufnehmen k"onnen
+       - Wenn saved=true, dann darf das Register w"ahrend Funktionsaufrufen
+         nicht zerst"ort werden.
+       - Wenn new=true, dann darf das Register noch NIE vorher vergeben 
+         worden sein.
+       
+       Alle so mit 'reg_allocate' belegten Register werden f"ur nachfolgende
+       Aufrufe von 'reg_allocate' gesperrt, sie d"urfen also nicht zweimal
+       hintereinander vergeben werden (eh klar!).
+           
+       Diese Funktion muss IMMER eine g"ultige 'reginfo'-Struktur erzeugen,
+       auch wenn vielleicht keine normalen Register mehr "ubrig sind. In 
+       solchen F"allen muss eben ein auf den Speicher ausgelagertes 
+       Register erzeugt werden.
+        
+        
+void *reg_free(reginfo *r)
+       Gibt ein durch reg_allocate angefordertes Register tempor"ar wieder
+       frei. Dabei darf die 'reginfo'-Struktur aber NICHT zerst"ort werden,
+       weil sie vom Compiler sp"ater wieder gebraucht wird.
+       Das solchermassen frei gewordene CPU-Register (nicht diese reginfo-
+       Struktur) darf aber bei einem folgendem Aufruf von reg_allocate 
+       wieder vergeben werden.
+
+
+bool reg_reallocate (reginfo *r)
+       versucht ein schon einmal angefordertes (aber in der Zwischenzeit 
+       wieder freigegebenens) Register neuerlich anzufordern. 
+       Wenn das Register immer noch unbenutzt ist, dann ist alles OK 
+       (R"uckgabewert true), sonst wird 'false' zur"uckgeben, und aus der
+       neuerlichen Belegung wird nichts. In diesem Falle wird der Compiler
+       versuchen, mit 'reg_allocate' ein ganz neues Register anzufordern.
+
+void reg_display (reginfo *r)
+       dient nur zu Debug-Zwecken, und gibt eine lesbare Darstellung des
+       mit 'reginfo' beschriebenen Registers auf 'stdout' aus.
+
+
+       
+Die nachfolgenden Funktionen sind f"ur die Optimierung der Funktionsaufrufe,
+bzw. der Registerbenutzung im Zusammenhang mit Funktionsaufrufen bestimmt.
+Jede dieser Funktionen darf entweder NULL zur"ckliefern (als allererste
+nichtoptimierte Version), oder aber eine entsprechende 'reginfo'-Struktur.
+reginfo *reg_parlistresult(u2 type)
+       erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+       beschreibt, mit den normalerweise ein Datum vom Typ type von
+       Funktionen zur"uckgeliefert wird.
+       Diese Funktion wird auch schon vor dem Aufruf von 'reg_init' verwendet,
+       Diese Funktion selbst blockiert noch kein Register, und sie braucht auch 
+       keine R"ucksicht auf irgendwelche schon durchgef"uhrten Registerbelegungen 
+       nehmen. Die tats"achliche Allokation wird sp"ater mit einem Aufruf
+       von 'reg_reallocate' versucht.
+       
+reginfo *reg_parlistexception()
+       erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+       beschreibt, mit den normalerweise der Zeiger auf eine Exception von
+       Funktionen zur"uckgeliefert wird.
+       Ansonsten v"ollig analog zu 'reg_parlistresult'
+
+reginfo *reg_parlistpar(u2 type)
+       erzeugt eine 'reginfo'-Struktur (auf dem DUMP), die das CPU-Register
+       beschreibt, mit dem normalerweise ein Datum vom Typ type als Parameter
+       an eine Funktion "ubergeben wird.
+       Diese Funktion wird im allgemeinen mehrmals hintereinander aufgerufen,
+       n"amlich f"ur jedes gew"unschte Parameterregister einmal.
+       Jede solche Sequenz wird mit 'reg_parlistinit' eingeleitet.
+       Ansonsten funktioniert diese Funktion wie 'reg_parlistresult'.
+       Achtung: Diese Funktion sollte gegebenenfalls auch maximale Anzahl
+         der Parameter bei Funktionsaufrufen notieren, wenn diese Information
+         sp"ater vom Codegenerator gebraucht wird.
+        
+void reg_parlistinit ()
+       Setzt den Parameterz"ahler, den die Funktion 'reg_parlistpar' intern
+       ben"otigen wird, auf 0.
+
+
+-------------------------------------------------------------------------------
+2. Der Codegenerator (gen.c)
+-------------------------------------------------------------------------------
+
+Der Compiler erzeugt im ersten Durchgang eine systemunabh"angige Darstellung
+einer Methode (Operationen mit Quell- und Ziel(pseudo)registern).
+Im zweiten Durchgang werden alle Pseudoregister mit tats"achlichen Registern
+belegt (siehe oben), und
+im dritten Durchgang wird der tats"achliche Code erzeugt (eben durch
+den Codegenerator).
+
+Der Codegenerator besteht aus mehreren Teilen:
+
+
+void gen_computestackframe()
+       berechnet das Memory-Layout des Stackframe f"ur die Methode.
+       Dabei m"ussen alle Register, die vom Register-Allokator vergeben
+       worden, sind und die Anzahl der zu sichernden Register und
+       die maximale Anzahl der Parameter ber"ucksichtigt werden.
+
+void gen_header()
+       erzeugt den Kopf der Methode (Anlegen des Stackframes, sichern von 
+       Registern, holen der Parameter vom Stack oder von Registern, etc..)
+       
+void gen_pcmd (pcmd *c)
+       erzeugt zu einem Pseudo-Kommando den entsprechenden Maschinencode.
+       Eine Beschreibung der pcmd-Struktur und aller f"ur den Codegenerator
+       relevanten globalen Variablen und Funktionen sind weiter unten beschrieben.
+       
+void gen_resolvebranch ( void* mcodepiece, u4 sourcepos, u4 targetpos)
+       tr"agt eine tats"achlien Sprungadresse in den vorher erzeuten
+       Maschinencode ein (Backpatching). 
+       Parameter: mcodepiece ... Zeiger in den Speicher, wo der entsprechende
+                                 Sprungbefehl steht
+                  sourcepos .... relative Adresse des Sprungbefehls in Byte
+                                 (vom Methodenbeginn an gerechnet)
+                  targetpos .... relative Adresse des Sprungziels in Byte
+                                 (vom Methodenbeginn an gerechnet)
+
+
+Alle Literale, die der Codegenerator erzeugt (konstante Integers,
+Addressen,...) werden in einem direkt VOR dem Codesegment liegenden
+Datensegment gespeichert.
+Dabei w"achst das Datensegment von oben nach unten, und das Codesegment
+von unten nach oben.
+Die Addressierung sowohl des Codes, als auch der Daten kann dann
+"uber ein einziges Basisregister (auf der ALPHA ist das das Register
+ R27 = PV ).
+Der Codegenerator greift auf diese beiden Segmente nur "uber spezielle
+Funktionen zu, die den Speicher f"ur die Segmente gegebenenfalls 
+vergr"ossern k"onnen.
+Am Ende der Generierung wird ein dann einziger Speicherblock angelegt,
+wo beide Segmente passgenau hineingeschrieben werden.
+
+3. Der Disassembler (disass.c)
+-------------------------------------------------------------------------------
+
+Der Disassembler dient nur zu Debug-Zwecken und kann durch eine Dummy-Funktion
+ersetzt werden.
+
+Der Disassembler hat nur eine Funktion:
+
+disassemble(u4 *code, u4 len)
+       erzeugt ein lesbares Listing der Maschinenbefehle, die im Speicher 
+       an der angegebenen Stelle stehen. Die L"ange des Maschinenprogrammes
+       wird hier in BYTE angegeben.
+       Das Listing wird auf 'stdout' ausgegeben.
+                
+
+
+------------------------------------------------------------------------------
+Beschreibung der globalen Variablen und Methoden
+------------------------------------------------------------------------------
+
+Der Codegenerator braucht f"ur seine Arbeit einige Funktionen und 
+Variablen, die im systemUnabh"angigen Teil bereits zur Verf"ugung stehen.
+
+
+Funktionen
+----------
+
+mcode_addu4 (u4 codepiece)
+       f"ugt zum aktuell erzeugten Codesegment ein 32-Byte-Wort hinzu.
+       Damit sollten sich alle Maschinenbefehle (zumindest f"ur RISC) 
+       erzeugen lassen.
+       
+s4 dseg_adds4 (s4 value)
+s4 dseg_adds8 (s8 value)
+s4 dseg_addfloat (float value)
+s4 dseg_adddouble (double value)
+s4 dseg_addaddress (void *value)
+       diese Funktionen f"ugen das entsprechende Datum zum Datensegment
+       der Methode hinzu. Das Alignment wird auf jeden Fall richtig 
+       behandelt.
+       
+       Alle diese Funktionen liefern als R"uckgabewert den Offset des 
+       Datenelements innerhalb des Datensegments zur"uck. Weil das Datensegment
+       direkt vor dem Codesegment liegt, und alle Addressierungen
+       relativ zum Methodenanfang (also zum Anfang des Codes) passieren,
+       sind diese Offsets immer negativ.
+
+s4 dseg_addtarget (basicblock *target)
+       funktioniert im Prinzip so wie die obigen Funktionen, allerdings
+       wird in das Datensegment ein Zeiger auf eine Codeposition (deren
+       genaue Adresse aber noch gar nicht feststeht) eingetragen.
+       Die tats"achliche Adresse wird ganz am Ende der Codeerzeugung 
+       automatisch     an die richtige Stelle geschrieben, so dass beim 
+       Programmlauf auf jeden Fall der richtige Wert dort steht.
+       (Diese Funktion wird wahrscheinlich vor allem f"ur Sprungtabellen
+       von Bedeutung sein)
+       
+
+void mcode_addreference (basicblock *target)
+       Mit dieser Funktion macht der Codegenerator einen Eintrag in die
+       Liste der der sp"ater zu vervollst"andigenden Sprungbefehle.
+       Die Vorgehensweise ist folgende:
+       - Wenn der Codegenerator ein (Vorw"arts-)Sprunganweisung erzeugen will,
+         dann ruft er VORHER mcode_addreference auf (als Parameter
+         die entsprechende basicblock-Struktur)
+       - Dann erzeugt der Codegenerator einen Sprungbefehl (mit mcode_addu4), 
+         l"asst dabei aber die Zieladdresse leer (weil sie ja noch nicht 
+         feststeht)
+       - sobald der Code fertig erzeugt worden ist (und alle Sprungziele 
+         feststehen) wird f"ur jeden so vorbereiteten Sprungbefehl die
+         Funktion gen_resolvebranch (Dokumentation siehe dort) aufgerufen.
+
+         
+
+Globale Variablen
+-----------------
+
+bool isleafmethod
+       zeigt an, dass die Methode eine Leaf-Methode ist, d.h, dass sie keine
+       weiteren Methoden oder Funktionen aufruft
+
+u2 mparamnum 
+       die Anzahl der Parameter f"ur die Methode, inklusive dem 
+       this-Zeiger (aber um den this-Zeiger braucht sich der Codegenerator
+       sowieso nicht extra k"ummern)
+
+u2 *mparatypes
+       ein Zeiger auf ein Array von Integers, die die Java-Grundtypen 
+       (TYPE_INT, TYPE_LONG,...) der Parameter angeben
+
+u2 mreturntype
+       gibt den Java-Grundtyp des R"uckgabewertes an (TYPE_INT, TYPE_LONG)
+       oder bei Methoden ohne R"uckgabewert: TYPE_VOID
+
+varinfo **mparamvars
+       ein Zeiger auf ein Array von Zeigern auf die varinfo-Strukturen.
+       Diese varinfos geben die Pseudoregister an, in die die Parameter
+       der Methode nach dem Aufruf geschrieben werden sollen (der Code
+       f"ur dieses (eventuell n"otige) Umladen der Werte muss von
+       gen_header erzeugt werden).
+       
+       
+------------------------------------------------------------------------------
+die varinfo-Struktur
+------------------------------------------------------------------------------
+
+In den Pseudocommandos (pcmd) stehen als Operanden immer Verweise auf 
+Pseudoregister, denen w"ahrend der Registerbelegungsphase echte
+Maschinenregister zugewiesen werden.
+F"ur den nachfolgenden Codegenerator ist dann nur mehr das entsprechende
+Maschinenregister von Bedeutung. 
+Der Codegenerator darf in der varinfo-Struktur nur auf das Feld 
+'reg' zugreifen, das einen Zeiger auf die entsprechende 'reginfo'-Struktur
+(wie sie vom Registerallokator erzeugt worden ist -> siehe oben) enth"alt.
+Der Codegenerator kann sich darauf verlassen, dass jeder varinfo-Struktur,
+die "uber ein pcmd erreichbar ist, auch ein entsprechendes reginfo zugewiesen
+wurde.
+
+
+
+------------------------------------------------------------------------------
+Die pcmd-Struktur
+------------------------------------------------------------------------------
+
+Hier finden sich alle Informationen, die die Funktion 'gen_pcmd' 
+braucht, um damit Maschinencode f"ur ein Pseudokommando zu erzeugen.
+Die Syntax dieser Struktur (mit Kommentaren) befindet sich unter anderem
+in der Datei 'defines.c'.
+
+F"ur verschiedene Typen von Kommandos muss die Struktur verschiedene
+Daten enthalten, deshalb ist sie mit Hilfe einer 'union' realisiert,
+und ein tag-Feld gibt den tats"achlichen Typ der Struktur an (jaja, in
+C gibt es eben keine abgeleiteten Datentypen ...).
+Die Werte und Bezeichnung f"ur dieses Tag-Feld steht ebenfalls in der 
+Datei 'defines.c'
+
+
+Beschreibung der allgemeinen Felder der 'pcmd'.
+
+       linkage ... interne Verkettung, f"ur den Codegenerator ohne Bedeutung)
+       tag ....... Kennzeichnung des Typs des Kommandos
+       
+       dest ...... Pseudoregister f"ur eine optionalen Zieloperanden
+       source1 ... Pseudoregister f"ur den 1. optionalen Quelloperanden
+       source2 ...                         2.
+       source3 ...                         3.
+       
+Alle Kommandos (ausser unbedingten Spr"ungen) haben in irgendeiner Form
+Operanden-Register. Dabei stehen Register aus denen ein Wert geholt wird
+in den Feldern source1-source3, und ein Register in das ein Wert geschrieben
+wird, steht im Feld dest. Alle unbenutzen Felder haben immer den
+Wert NULL.
+
+Alle Befehle haben eine genau definierte Anzahl von Operanden, deren
+Typ ausserdem auf jeden Fall stimmt (die Register wurden zuvor mit
+'reg_allocate' unter Angabe des richtigen Typs angefordert).
+
+
+Die Befehlstypen
+----------------
+
+       LOADCONST_I
+       LOADCONST_L
+       LOADCONST_F
+       LOADCONST_D
+       LOADCONST_A 
+               Jeder dieser Befehle l"adt einen Wert vom entsprechenden
+               Typ in das Zielregister.
+               Diese konstanten Werte selber stehen in 
+               pcmd->i.value, pcmd->l.value ...
+               
+       MOVE
+               Kopiert einen Wert vom Quellregister 1 ins Zielregister.
+               Beide Register haben den Typ pcmd->move.type .
+               
+       OP
+               F"uhrt eine JavaVM-Grundoperation aus.
+               Im Feld pcmd->op.opcode steht der JavaVM-Opcode des gew"unschten
+               Befehls.
+               Die Anzahl und die Typen der Operanden sind f"ur jede Operation
+               anders. Eine genaue Beschreibung der Semantik findet sich
+               in der JavaVM-Spezifikation. Dabei sind die Quelloperanden
+               in der Reihenfolge wie sie in der Spezifikation am Stack stehen
+               (von links nach rechts), in die Quellregister 1 bis 3 aufgeteilt.
+               Bei Operanden vom Typ LONG oder DOUBLE sind beide 'value-words'
+               in einem Register zusammengefasst.
+
+       MEM
+               L"adt entweder einen Wert aus dem Speicher, oder schreibt
+               einen Wert dorthin.
+               Das Feld pcmd->mem.opcode enth"alt dazu entweder CMD_GETFIELD
+               oder CMD_PUTFIELD.
+               In pcmd->mem.type steht der Java-Grunddatentyp dieses
+               Feldes, und in pcmd->mem.offset steht der konstante Offset (in Byte),
+               der zum Basisregister (pcmd->source1) addiert werden soll, um die 
+               tats"achliche Speicheradresse des Felds zu bekommen.
+               Bei Ladeoperationen steht das Ergebnis nachher im Register 
+               pcmd->dest, bei Speicheroperationen steht der zu speichernde
+               Wert im Register pcmd->source2.
+               
+       BRA
+               F"uhrt bedingte oder unbedingte Spr"unge aus. Im Feld 
+               pcmd->bra.opcode steht der entsprechende JavaVM-Opcode.
+               Die Operanden (die laut JavaVM-Spec am Stack stehen m"ussen)
+               sind in den Registern pcmd->source1 und pcmd-source2 zu finden
+               (ganz analog zu dene OP-Kommandos).
+               Spezielle Formen: 
+                       JSR: Hier soll die R"ucksprungadresse ins Register pcmd-dest
+                            geschrieben werden.
+                       RET: Obwohl laut JavaVM-Spec dieser Befehl den Stack nicht
+                            beeinflusst, hat er dennoch einen Operanden: pcmd->source1
+                            enth"alt die R"ucksprungadresse 
+                               
+                       IRETURN bis ARETURN
+                       und RETURN:
+                                in pcmd->source1 befindet sich der R"uckgabewert
+                                (ausgenommen bei RETURN), und
+                                in pcmd->source2 ist der Zeiger auf die zu werfende
+                                Exception.
+       
+               Das Sprungziel (insofern bei dem Befehl eines m"oglich ist) wird
+               als Zeiger auf eine basicblock-Struktur "ubergeben. 
+               Zum Aufl"osen der Sprungziele siehe: mcode_addreference.
+               
+       TABLEJUMP
+               Fu"hrt eine Programmverzweigung "uber eine Sprungtabelle durch.                 
+               Der einzige Operand (pcmd->source1) ist im Bereich von
+               i = 0 .. pcmd->tablejump.targetcount-1. Der Befehl soll an das
+               dementsprechende Sprungziel pcmd->tablejump.targets[i] verzweigen.
+               Zur Konstruktion einer Sprungtabelle siehe: dseg_addtarget.
+
+
+       METHOD
+               F"uhrt einen Methoden (bzw. C-Funktions-) -aufruf durch. 
+               Die Felder pcmd->method.paramnum und pcmd->method.params[..] 
+               geben die Anzahl und die Register an, in denen die Parameter
+               stehen. Unter (g"unstigen) Umst"anden sind einige der Register
+               schon diejenigen, die durch die Aufrufkonventionen die Parameter
+               enthalten sollen (wenn das nicht der Fall ist, dann m"ussen
+               die Werte vor dem Aufruf noch umgeladen werden).
+               Das Feld pcmd->method.exceptionvar enth"alt (wenn es nicht
+               NULL ist) die Variable, in der eine allf"allig aufgetretene
+               Exception zur"uckerwartet wird.
+               Der normale R"uckgabewert der Methode soll ins Register
+               pcmd->dest geschrieben werden.
+
+               Dieses Pseudokommando wird sowohl f"ur Aufrufe von normalen
+               C-Funktionen (dann steht im Feld pcmd->method->builtin der
+               Zeiger auf diese Funktion) als auch f"ur Aufrufe von Java-Methoden
+               verwendet (dann steht im Feld pcmd->method->builtin der 
+               Wert NULL).
+               
+               Im zweiten Fall enth"alt das Feld pcmd->method->method einen
+               Zeiger auf die methodinfo-Struktur der gew"unschten Methode.
+               Bei Aufrufen vom Typ INVOKESTATIC und INVOKESPECIAL 
+               (der Typ steht in pcmd->method->opcode) braucht dazu nur
+               der Funktionszeiger von dort geladen werden. 
+               Bei INVOKEVIRTUAL und INVOKEINTERFACE muss der Funktionszeiger
+               aus der Virtual Function Table der Klasse des tats"achlichen 
+               Objektes geholt werden. Der Zeiger auf dieses Objekt ist immer
+               im Register pcmd->method->params[0] zu finden.
+               Eine Beschreibung dieser Tabellen steht in der Datei "global.h".
+               
+               WICHTIG: Dieses System compiliert alle Methoden beim ersten 
+                       Aufruf, deshalb m"ussen alle Methodenaufrufe immer mit dem
+                       Umweg "uber die methodinfo-Struktur passieren, weil nur dort
+                       dann der tats"achliche Funktionszeiger eingetragen wird.
+                       Wenn die Methode n"amlich noch nicht aufgerufen wurde, dann 
+                       steht dort ein Zeiger auf den Compiler selbst.
+                       Der Compiler ben"otigt f"ur seine Arbeit aber noch zus"atzlich
+                       den Zeiger auf die methodinfo-Struktur in einem fixen
+                       Register. Auf der DEC-ALPHA verwende ich hier das Register 28.
+                       Die Aufrufsequenz auf der DEC-ALPHA f"ur einen normalen
+                       INVOKESTATIC-Aufruf w"urde ungef"ahr so aussehen:
+                               
+                               LDQ (28, 27, position_des_methodinfo_zeigers_im_datensegment)
+                               LDQ (27, 28, OFFSET(methodinfo, func) )
+                               JSR (26, 27)
+                               LDA (27, 26, -position_dieses_befehls_im_code)
+               
+               
+               
+
+-------------------------------------------------------------------------------
+Anhang: Notwendige Opcodes
+
+F"ur die Befehle vom Typ OP m"ussen folgende Opcodes unterst"utzt werden:
+                CMD_INEG
+                CMD_LNEG
+                CMD_FNEG
+                CMD_DNEG
+                CMD_I2L
+                CMD_L2I
+                CMD_INT2BYTE
+                CMD_INT2CHAR
+                CMD_INT2SHORT
+                CMD_IADD
+                CMD_LADD
+                CMD_FADD
+                CMD_DADD
+                CMD_ISUB
+                CMD_LSUB
+                CMD_FSUB
+                CMD_DSUB
+                CMD_IMUL
+                CMD_LMUL
+                CMD_FMUL
+                CMD_DMUL
+                CMD_FDIV
+                CMD_DDIV
+                CMD_FREM
+                CMD_DREM
+                CMD_ISHL
+                CMD_ISHR
+                CMD_IUSHR
+                CMD_LSHL
+                CMD_LSHR
+                CMD_LUSHR
+                CMD_IAND
+                CMD_LAND
+                CMD_IOR
+                CMD_LOR
+                CMD_IXOR
+                CMD_LXOR
+                CMD_I2F
+                CMD_L2F
+                CMD_I2D
+                CMD_L2D
+                CMD_F2I
+                CMD_D2I
+                CMD_F2L
+                CMD_D2L
+                CMD_F2D
+                CMD_D2F
+                CMD_LCMP
+                CMD_FCMPL
+                CMD_DCMPL
+                CMD_FCMPG
+                CMD_DCMPG
+                CMD_ARRAYLENGTH
+                CMD_AALOAD
+                CMD_LALOAD
+                CMD_IALOAD
+                CMD_FALOAD
+                CMD_DALOAD
+                CMD_CALOAD
+                CMD_SALOAD
+                CMD_BALOAD
+                CMD_AASTORE
+                CMD_LASTORE
+                CMD_IASTORE
+                CMD_FASTORE
+                CMD_DASTORE
+                CMD_CASTORE
+                CMD_SASTORE
+                CMD_BASTORE
+
+F"ur die Befehle vom Typ MEM m"ussen folgende Opcodes unterst"utzt werden:
+                CMD_PUTFIELD:
+                CMD_GETFIELD:
+
+
+F"ur die Befehle vom Typ BRA m"ussen folgende Opcodes unterst"utzt werden:
+                CMD_GOTO
+                CMD_JSR
+                CMD_RET
+                CMD_IFEQ
+                CMD_IFNULL
+                CMD_IFLT
+                CMD_IFLE
+                CMD_IFNE
+                CMD_IFNONNULL
+                CMD_IFGT
+                CMD_IFGE
+                CMD_IF_ICMPEQ
+                CMD_IF_ACMPEQ
+                CMD_IF_ICMPNE
+                CMD_IF_ACMPNE
+                CMD_IF_ICMPLT
+                CMD_IF_ICMPGT
+                CMD_IF_ICMPLE
+                CMD_IF_ICMPGE
+                CMD_IRETURN
+                CMD_LRETURN
+                CMD_ARETURN
+                CMD_FRETURN
+                CMD_DRETURN
+                CMD_RETURN
+
+
+
+F"ur die Befehle vom Typ METHOD m"ussen folgene Opcodes unterst"utzt werden:
+                CMD_INVOKESTATIC
+                CMD_INVOKESPECIAL
+                CMD_INVOKEVIRTUAL
+                CMD_INVOKEINTERFACE
diff --git a/global.h b/global.h
new file mode 100644 (file)
index 0000000..e92f7f1
--- /dev/null
+++ b/global.h
@@ -0,0 +1,542 @@
+/****************************** global.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains global definitions which are used in the whole program, includes
+       some files and contains global used macros.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Chages:  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/28
+
+*******************************************************************************/
+
+#ifndef __global_h_
+#define __global_h_                        /* schani */
+
+#define STATISTICS                         /* andi   */
+
+/***************************** standard includes ******************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "toolbox/memory.h"
+#include "toolbox/chain.h"
+#include "toolbox/list.h"
+#include "toolbox/loging.h"
+
+
+/**************************** system dependent types **************************/
+
+#include "sysdep/types.h"
+
+
+/**************************** additional data types ***************************/
+
+typedef void *voidptr;          /* generic pointer */
+
+
+typedef u1    bool;             /* boolean data type */
+
+#define true  1
+#define false 0
+
+typedef void (*functionptr) (); /* generic function pointer */
+
+
+#define MAX_ALIGN 8             /* most generic alignment for JavaVM values   */
+
+
+/**************************** shutdown function *******************************/
+
+void cacao_shutdown(s4 status);
+
+
+/**************************** basic data types ********************************/
+
+#define TYPE_INT      0         /* the JavaVM types must numbered in the      */
+#define TYPE_LONG     1         /* same order as the ICMD_Ixxx to ICMD_Axxx   */
+#define TYPE_FLOAT    2         /* instructions (LOAD and STORE)              */
+#define TYPE_DOUBLE   3         /* integer, long, float, double, address      */
+#define TYPE_ADDRESS  4         /* all other types can be numbered arbitrarily*/
+
+#define TYPE_VOID    10
+
+
+/**************************** Java class file constants ***********************/
+
+#define MAGIC         0xcafebabe
+#define MINOR_VERSION 3
+#define MAJOR_VERSION 45
+
+#define CONSTANT_Class                7
+#define CONSTANT_Fieldref             9
+#define CONSTANT_Methodref           10
+#define CONSTANT_InterfaceMethodref  11
+#define CONSTANT_String               8
+#define CONSTANT_Integer              3
+#define CONSTANT_Float                4
+#define CONSTANT_Long                 5
+#define CONSTANT_Double               6
+#define CONSTANT_NameAndType         12
+#define CONSTANT_Utf8                 1
+
+#define CONSTANT_Arraydescriptor     13
+#define CONSTANT_UNUSED               0
+
+
+#define ACC_PUBLIC                0x0001
+#define ACC_PRIVATE               0x0002
+#define ACC_PROTECTED             0x0004
+#define ACC_STATIC                0x0008
+#define ACC_FINAL                 0x0010
+#define ACC_SYNCHRONIZED          0x0020
+#define ACC_VOLATILE              0x0040
+#define ACC_TRANSIENT             0x0080
+#define ACC_NATIVE                0x0100
+#define ACC_INTERFACE             0x0200
+#define ACC_ABSTRACT              0x0400
+
+
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct unicode unicode;
+typedef struct classinfo classinfo; 
+typedef struct vftbl vftbl;
+typedef u1* methodptr;
+
+
+/********************** data structures of UNICODE symbol *********************/
+
+struct unicode {
+       unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+       u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+       int        length;   /* L"ange des Textes */           
+       u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+       classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
+                               Namens (oder NULL, wenn es keine solche gibt)  */
+       struct java_objectheader *string;
+                            /* gegebenenfalls Referenz auf einen konstanten
+                               String mit dem entsprechenden Wert */ 
+       };
+
+       /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
+          (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
+          -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
+          Zeigervergleich */
+
+
+/************ data structures of remaining constant pool entries **************/
+
+
+typedef struct {
+       classinfo *class;
+       unicode   *name;
+       unicode   *descriptor;
+       } constant_FMIref;
+
+
+typedef struct {
+       s4 value;
+       } constant_integer;
+       
+typedef struct {
+       float value;
+       } constant_float;
+
+typedef struct {
+       s8 value;
+       } constant_long;
+       
+typedef struct {
+       double value;
+       } constant_double;
+
+
+typedef struct {
+       unicode *name;
+       unicode *descriptor;
+       } constant_nameandtype;
+
+
+typedef struct constant_arraydescriptor {
+       int arraytype;
+       classinfo *objectclass;
+       struct constant_arraydescriptor *elementdescriptor;
+       } constant_arraydescriptor;
+
+       /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+          Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
+       dass das Feld arraytype die entsprechende Kennzahl enth"alt
+       (z.B. ARRAYTYPE_BYTE).
+       Bei Arrays von Objekten (arraytype=ARRAYTYPE_OBJECT) muss das 
+       Feld objectclass auf die Klassenstruktur der m"oglichen
+       Element-Objekte zeigen.
+       Bei Arrays von Arrays (arraytype=ARRAYTYPE_ARRAY) muss das
+       Feld elementdescriptor auf eine weiter arraydescriptor-Struktur
+       zeigen, die die Element-Typen beschreibt.
+       */
+
+
+
+/********* Anmerkungen zum Constant-Pool:
+
+       Die Typen der Eintr"age in den Constant-Pool werden durch die oben
+       definierten CONSTANT_.. Werte angegeben.
+       Bei allen Typen muss zus"atzlich noch eine Datenstruktur hinzugef"ugt
+       werden, die den wirklichen Wert angibt.
+       Bei manchen Typen reicht es, einen Verweis auf eine schon bereits
+       existierende Struktur (z.B. unicode-Texte) einzutragen, bei anderen
+       muss diese Struktur erst extra erzeugt werden.
+       Ich habe folgende Datenstrukturen f"ur diese Typen verwendet:
+       
+               Typ                      Struktur                    extra erzeugt?
+       ----------------------------------------------------------------------
+    CONSTANT_Class               classinfo                         nein
+    CONSTANT_Fieldref            constant_FMIref                     ja
+    CONSTANT_Methodref           constant_FMIref                     ja
+    CONSTANT_InterfaceMethodref  constant_FMIref                     ja
+    CONSTANT_String              unicode                           nein
+    CONSTANT_Integer             constant_integer                    ja
+    CONSTANT_Float               constant_float                      ja
+    CONSTANT_Long                constant_long                       ja
+    CONSTANT_Double              constant_double                     ja
+    CONSTANT_NameAndType         constant_nameandtype                ja
+    CONSTANT_Utf8                unicode                           nein
+    CONSTANT_Arraydescriptor     constant_arraydescriptor            ja
+    CONSTANT_UNUSED              -
+
+*******************************/
+
+
+
+/***************** Die Datenstrukturen fuer das Laufzeitsystem ***************/
+
+
+       /********* Objekte **********
+
+       Alle Objekte (und Arrays), die am Heap gespeichert werden, m"ussen eine 
+       folgende spezielle Datenstruktur ganz vorne stehen haben: 
+
+       */
+
+typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
+       vftbl *vftbl;                     /* Zeiger auf die Function Table */
+} java_objectheader;
+
+
+
+       /********* Arrays ***********
+       
+       Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
+       den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
+       Es gibt aber (der Einfachheit halber) nur eine einzige Klasse f"ur alle
+       m"oglichen Typen von Arrays, deshalb wird der tats"achliche Typ in einem
+       Feld im Array-Objekt selbst gespeichert.
+       Die Typen sind: */
+
+#define ARRAYTYPE_INT      0
+#define ARRAYTYPE_LONG     1
+#define ARRAYTYPE_FLOAT    2
+#define ARRAYTYPE_DOUBLE   3
+#define ARRAYTYPE_BYTE     4
+#define ARRAYTYPE_CHAR     5
+#define ARRAYTYPE_SHORT    6
+#define ARRAYTYPE_BOOLEAN  7
+#define ARRAYTYPE_OBJECT   8
+#define ARRAYTYPE_ARRAY    9
+
+
+       /** Der Header f"ur ein Java-Array **/
+
+typedef struct java_arrayheader {  /* Der Arrayheader f"ur alle Arrays */
+       java_objectheader objheader;       /* Der Object-Header */
+       s4 size;                           /* Gr"osse des Arrays */
+       s4 arraytype;                      /* Typ der Elemente */
+} java_arrayheader;
+
+
+
+       /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+
+typedef struct java_chararray {
+       java_arrayheader header;
+       u2 data[1];
+} java_chararray;
+
+typedef struct java_floatheader {
+       java_arrayheader header;
+       float data[1];
+} java_floatarray;
+
+typedef struct java_doublearray {
+       java_arrayheader header;
+       double data[1];
+} java_doublearray;
+
+
+   /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
+      identisches memory-layout haben, weil mit den selben Funktionen 
+      darauf zugegriffen wird */
+
+typedef struct java_booleanarray {
+       java_arrayheader header;
+       u1 data[1];
+} java_booleanarray;
+
+typedef struct java_bytearray {
+       java_arrayheader header;
+       s1 data[1];
+} java_bytearray;
+
+typedef struct java_shortarray {
+       java_arrayheader header;
+       s2 data[1];
+} java_shortarray;
+
+typedef struct java_intarray {
+       java_arrayheader header;
+       s4 data[1];
+} java_intarray;
+
+typedef struct java_longarray {
+       java_arrayheader header;
+       s8 data[1];
+} java_longarray;
+
+
+       /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+          Memory-Layout haben, weil mit ein und der selben Funktion auf die
+          data-Eintr"age beider Typen zugegriffen wird !!!! */
+
+typedef struct java_objectarray {
+       java_arrayheader header;
+       classinfo *elementtype;
+       java_objectheader *data[1];
+} java_objectarray;
+
+typedef struct java_arrayarray {
+       java_arrayheader header;
+       constant_arraydescriptor *elementdescriptor;
+       java_arrayheader *data[1];
+} java_arrayarray;
+
+
+
+
+/************** Strukturen f"ur Klassen, Felder & Methoden *****************/
+
+
+    /*** Struktur: fieldinfo ***/
+
+typedef struct fieldinfo {   /* Struktur f"ur ein Feld einer Klasse */
+       s4       flags;              /* die ACC-Flags */
+       s4       type;               /* Grunddatentyp */
+       unicode *name;               /* Name des Felds */
+       unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
+       
+       s4       offset;             /* Offset vom Anfang des Objektes */
+                                    /* (bei Instanzvariablen) */
+
+       union {                      /* Speicher f"ur den Wert */
+               s4 i;                    /* (bei Klassenvariablen) */    
+               s8 l;
+               float f;
+               double d;
+               void *a; 
+               } value;
+               
+       } fieldinfo;
+
+
+    /*** Struktur: exceptiontable ***/
+
+typedef struct exceptiontable {  /* Exceptionhandler-Eintrag in einer Methode */ 
+       s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
+       s4         endpc;              /* Ende des Bereichs (exklusive) */
+       s4         handlerpc;          /* JavaVM-Position des Handlers */
+       classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
+                                       NULL, wenn alle behandelt werden sollen) */
+       } exceptiontable;
+
+
+
+    /*** Struktur: methodinfo ***/
+
+typedef struct methodinfo {  /* Struktur f"ur eine Methode einer Klasse */
+       s4             flags;            /* die ACC-Flags */
+       unicode   *name;             /* Name der Methode */
+       unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
+       s4        returntype;        /* only temporary valid, return type */
+       s4        paramcount;        /* only temporary valid, number of parameters */
+       u1        *paramtypes;       /* only temporary valid, parameter types */
+       classinfo *class;            /* Die Klasse, der die Methode geh"ort */
+       u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
+                                       Function Table (wenn es keine statische
+                                       Methode ist) */
+
+       s4       maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
+       s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
+       u4   jcodelength;               /* L"ange des JavaVM-Codes */
+       u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
+
+       s4   exceptiontablelength;      /* L"ange der Exceptintable */
+       exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+       u1  *stubroutine;               /* STUB-Routine for compiling or calling 
+                                          natives */   
+       u4   mcodelength;               /* L"ange des generierten Maschinencodes */
+       u1  *mcode;                     /* Zeiger auf den Maschinencode */
+       u1  *entrypoint;                /* Entrypoint to the Maschine-Code */
+
+       
+       } methodinfo;
+
+
+    /*** Struktur: classinfo ***/
+
+struct classinfo {           /* Datenstruktur f"ur eine Klasse */
+       java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
+                                        werden */
+
+       s4 flags;                     /* Die ACC-Flags */
+       unicode *name;                /* Name der Klasse */ 
+       
+       s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
+       u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
+       voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
+       
+       classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
+       
+       s4          interfacescount;  /* Anzahl der Interfaces */
+       classinfo **interfaces;       /* Zeiger auf die Interfaces */
+       
+       s4          fieldscount;      /* Anzahl der Felder */
+       fieldinfo  *fields;           /* Die Tabelle der Felder */
+       
+       s4          methodscount;     /* Anzahl der Methoden */
+       methodinfo *methods;          /* Die Tabelle der Methoden */
+       
+       
+       listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
+
+       bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
+       bool        linked;           /* wird von `class_link` auf true gesetzt */
+       s4                      index;            /* Hierarchietiefe  (bei normalen Klassen)  
+                                        oder fortlaufende Nummer (bei Interfaces)*/ 
+       u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
+
+       vftbl       *vftbl;
+
+       methodinfo *finalizer;        /* Finalizer-Methode f"ur die Klasse */
+       };
+       
+
+struct vftbl {
+       classinfo  *class;            /* Class, the function table belongs to */
+
+       s4          vftbllength;      /* L"aenge der Virtual Function Table */
+
+       s4          interfacetablelength;   /* L"ange der Interfacetable */   
+       u4         *interfacevftbllength;   /* -> siehe unten */   
+       methodptr **interfacevftbl;
+       
+       methodptr   table[1];
+       };
+
+/*********** Anmerkungen zur Interfacetable: 
+
+       "Ahnlich wie die 'normalen' virtuellen Methoden k"onnen auch die
+       Interface-Methoden mit Hilfe einer Art Virtual Function Table 
+       aufgerufen werden.
+       Dazu werden alle Interfaces im System fortlaufend nummeriert (beginnend
+       bei 0), und f"ur jede Klasse wird eine ganze Tabelle von 
+       Virtual Function Tables erzeugt, n"amlich zu jedem Interface, das die
+       Klasse implementiert, eine.
+
+       z.B. Nehmen wir an, eine Klasse implementiert zwei Interfaces (die durch
+       die Nummerierung die Indizes 0 und 3 bekommen haben)
+
+       Das sieht dann ungef"ahr so aus:
+                               --------------           ------------- 
+       interfacevftbl ---> | Eintrag 0  |---------> | Methode 0 |---> Methode X 
+                        | Eintrag 1  |--> NULL   | Methode 1 |---> Methode Y
+                        | Eintrag 2  |--> NULL   | Methode 2 |---> Methode Z
+                        | Eintrag 3  |-----+     ------------- 
+                        --------------     |
+                                           +---> -------------
+                                                 | Methode 0 |---> Methode X
+                                                 | Methode 1 |---> Methode A
+                                                 -------------
+                              ---------------
+       interfacevftlblength ---> | Wert 0 = 3  |
+                                 | Wert 1 = 0  |
+                                 | Wert 2 = 0  |
+                                 | Wert 3 = 2  |
+                                 ---------------
+
+       Der Aufruf einer Interface-Methode geht dann so vor sich:
+       Zur Compilezeit steht der Index (i) des Interfaces und die Stelle (s), wo
+       in der entsprechenden Untertabelle die Methode eingetragen ist, schon fest.
+       Also muss zur Laufzeit nur mehr der n-te Eintrag aus der Interfacetable 
+       gelesen werden, von dieser Tabelle aus wird der s-te Eintrag geholt,
+       und diese Methode wird angesprungen.
+
+****************/
+
+
+
+/************************* Referenzen auf die wichtigen Systemklassen ********************/
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_ClassCastException;
+extern classinfo *class_java_lang_NullPointerException;
+extern classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+extern classinfo *class_java_lang_NegativeArraySizeException;
+extern classinfo *class_java_lang_OutOfMemoryError;
+extern classinfo *class_java_lang_ArithmeticException;
+extern classinfo *class_java_lang_ArrayStoreException;
+extern classinfo *class_java_lang_ThreadDeath;              /* schani */
+extern classinfo *class_array;
+
+
+/********************** Vorgefertigte Instanzen einiger Systemklassen ********************/
+
+extern java_objectheader *proto_java_lang_ClassCastException;
+extern java_objectheader *proto_java_lang_NullPointerException;
+extern java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+extern java_objectheader *proto_java_lang_NegativeArraySizeException;
+extern java_objectheader *proto_java_lang_OutOfMemoryError;
+extern java_objectheader *proto_java_lang_ArithmeticException;
+extern java_objectheader *proto_java_lang_ArrayStoreException;
+extern java_objectheader *proto_java_lang_ThreadDeath;      /* schani */
+
+
+/********************** flag variables *********************/
+
+extern bool compileall;
+extern bool runverbose;         
+extern bool verbose;         
+                                
+
+/********************** trace variables ********************/
+
+extern int count_class_infos;
+extern int count_const_pool_len;
+extern int count_vftbl_len;
+extern int count_unicode_len;
+extern int count_all_methods;
+extern int count_vmcode_len;
+extern int count_extable_len;
+
+#endif
diff --git a/headers.c b/headers.c
new file mode 100644 (file)
index 0000000..dce631e
--- /dev/null
+++ b/headers.c
@@ -0,0 +1,465 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** headers.c **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Dieser Modul ersetzt f"ur den Headerfile-Betrieb den Modul 'main',
+       und 'f"alscht' einige Verweise auf externe Module (damit nicht schon 
+       alle Module des eigentlichen Programmes fertig sein m"ussen, was ja
+       unm"oglich w"are, da die Headerfile-Tabellen ja erst hier und jetzt
+       generiert werden).
+
+       Dieser Modul ist ein ziemlich schneller Hack und dementsprechend
+       schlecht (nicht) kommentiert.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/05/23
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "loader.h"
+
+
+/******* verschiedene externe Funktionen "faelschen" (=durch Dummys ersetzen), 
+  damit der Linker zufrieden ist *********/
+functionptr native_findfunction 
+  (unicode *cname, unicode *mname, unicode *desc, bool isstatic)
+{ return NULL; }
+
+java_objectheader *literalstring_new (unicode *text)
+{ return NULL; }
+
+java_objectheader *javastring_new (unicode *text)         /* schani */
+{ return NULL; }
+
+void synchronize_caches() { }
+void asm_call_jit_compiler () { }
+void asm_calljavamethod () { }
+void asm_dumpregistersandcall () { }
+
+s4 new_builtin_idiv (s4 a, s4 b) {return 0;}
+s4 new_builtin_irem (s4 a, s4 b) {return 0;}
+s8 new_builtin_ldiv (s8 a, s8 b) {return 0;}
+s8 new_builtin_lrem (s8 a, s8 b) {return 0;}
+
+
+void new_builtin_monitorenter (java_objectheader *o) {}
+void new_builtin_monitorexit (java_objectheader *o) {}
+
+s4 new_builtin_checkcast(java_objectheader *o, classinfo *c)
+                        {return 0;}
+s4 new_builtin_checkarraycast
+       (java_objectheader *o, constant_arraydescriptor *d)
+       {return 0;}
+
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o) {}
+
+u1 *createcompilerstub (methodinfo *m) {return NULL;}
+u1 *createnativestub (functionptr f, methodinfo *m) {return NULL;}
+u1 *ncreatenativestub (functionptr f, methodinfo *m) {return NULL;}
+
+void removecompilerstub (u1 *stub) {}
+void removenativestub (u1 *stub) {}
+
+void perform_alpha_threadswitch (u1 **from, u1 **to) {}
+u1* initialize_thread_stack (void *func, u1 *stack) { return NULL; }
+u1* used_stack_top (void) { return NULL; }
+
+java_objectheader *native_new_and_init (void *p) { return NULL; }
+
+/************************ globale Variablen **********************/
+
+java_objectheader *exceptionptr;                       /* schani */
+int  newcompiler = true;
+bool verbose =  false;
+
+static chain *nativechain;
+static FILE *file = NULL;
+
+static void printIDpart (int c) 
+{
+               if (     (c>='a' && c<='z')
+                     || (c>='A' && c<='Z')
+                     || (c>='0' && c<='9')
+                     || (c=='_') )          
+                          putc (c,file);
+        else       putc ('_',file);
+
+}
+
+static void printID (unicode *name)
+{
+       int i;
+       for (i=0; i<name->length; i++) {
+               printIDpart (name->text[i]);
+       }
+}
+
+
+u4 outputsize;
+bool dopadding;
+
+static void addoutputsize (int len)
+{
+       u4 newsize,i;
+       if (!dopadding) return;
+
+       newsize = ALIGN (outputsize, len);
+       
+       for (i=outputsize; i<newsize; i++) fprintf (file, "   u1 pad%d\n",(int) i);
+       outputsize = newsize;
+}
+
+
+static u2 *printtype (u2 *desc)
+{
+       u2 c;
+
+       switch (*(desc++)) {
+               case 'V': fprintf (file, "void");
+                         break;
+               case 'I':
+               case 'S':
+               case 'B':
+               case 'C':
+               case 'Z': addoutputsize (4);
+                  fprintf (file, "s4");
+                  break;
+               case 'J': addoutputsize (8);
+                  fprintf (file, "s8");
+                  break;
+               case 'F': addoutputsize (4);
+                  fprintf (file, "float");
+                  break;
+               case 'D': addoutputsize (8);
+                  fprintf (file, "double");
+                  break;
+               case '[':
+                       addoutputsize ( sizeof(java_arrayheader*) ); 
+                       switch (*(desc++)) {
+                               case 'I':  fprintf (file, "java_intarray*"); break;
+                               case 'J':  fprintf (file, "java_longarray*"); break;
+                               case 'Z':  fprintf (file, "java_booleanarray*"); break;
+                               case 'B':  fprintf (file, "java_bytearray*"); break;
+                               case 'S':  fprintf (file, "java_shortarray*"); break;
+                               case 'C':  fprintf (file, "java_chararray*"); break;
+                               case 'F':  fprintf (file, "java_floatarray*"); break;
+                               case 'D':  fprintf (file, "java_doublearray*"); break;
+                               
+                               case '[':  fprintf (file, "java_arrayarray*");
+                                          while ((*desc) == '[') desc++;
+                                          if ((*desc)!='L') desc++;
+                                          else while (*(desc++) != ';');
+                           break;
+                           
+                               case 'L':  fprintf (file, "java_objectarray*");
+                                          while ( *(desc++) != ';');
+                                          break;
+                               default: panic ("invalid type descriptor");
+                               }
+                       break;
+               
+               case 'L': 
+                       addoutputsize ( sizeof(java_objectheader*));
+            fprintf (file, "struct ");
+            while ( (c = *(desc++)) != ';' ) printIDpart (c);           
+            fprintf (file, "*");
+                       break;
+                                       
+               default:  panic ("Unknown type in field descriptor");
+       }
+       
+       return (desc);
+}
+
+
+
+static void printfields (classinfo *c)
+{
+       u4 i;
+       fieldinfo *f;
+       
+       if (!c) {
+               addoutputsize ( sizeof(java_objectheader) );
+               fprintf (file, "   java_objectheader header;\n");
+               return;
+               }
+               
+       printfields (c->super);
+       
+       for (i=0; i<c->fieldscount; i++) {
+               f = &(c->fields[i]);
+               
+               if (! (f->flags & ACC_STATIC) ) {
+                       fprintf (file,"   ");
+                       printtype (f->descriptor->text);
+                       fprintf (file, " ");
+                       unicode_fprint (file, f->name);
+                       fprintf (file, ";\n");
+                       }
+               }
+}
+
+
+
+
+static void remembermethods (classinfo *c)
+{
+       u2 i;
+       methodinfo *m;
+
+       for (i=0; i<c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (m->flags & ACC_NATIVE) {
+                       chain_addlast (nativechain, m);
+                       }
+                                       
+               }
+}
+
+
+
+
+static void printmethod (methodinfo *m)
+{
+       u2 *d;
+       u2 paramnum=1;
+       
+       d = m->descriptor->text;
+       while (*(d++) != ')');
+                               
+       printtype (d);
+       fprintf (file," ");
+       printID (m->class->name);
+       fprintf (file,"_");
+       printID (m->name);
+       fprintf (file," (");
+                                       
+       d = m->descriptor->text+1;
+                       
+       if (! (m->flags & ACC_STATIC) ) {
+               fprintf (file, "struct ");
+               printID (m->class->name);
+               fprintf (file, "* this");
+               if ((*d)!=')') fprintf (file, ", ");
+               }
+                       
+       while ((*d)!=')') {
+               d = printtype (d);
+               fprintf (file, " par%d", paramnum++);
+               if ((*d)!=')') fprintf (file, ", ");
+               }
+                       
+       fprintf (file, ");\n");
+}
+
+
+static void headers_generate (classinfo *c)
+{
+       fprintf (file, "/* Structure information for class: ");
+       unicode_fprint (file, c->name);
+       fprintf (file, " */\n\n");
+
+       fprintf (file, "typedef struct ");
+       printID (c->name);
+       fprintf (file, " {\n");
+       
+       outputsize=0;
+       dopadding=true;
+       printfields (c);
+
+       fprintf (file, "} ");
+       printID (c->name);
+       fprintf (file, ";\n\n");
+
+       remembermethods (c);
+       
+
+       fprintf (file, "\n\n");
+}
+
+
+
+static void printnativetableentry (methodinfo *m)
+{
+       fprintf (file, "   { \"");
+       unicode_fprint (file, m->class->name);
+       fprintf (file, "\",\n     \"");
+       unicode_fprint (file, m->name);
+       fprintf (file, "\",\n     \"");
+       unicode_fprint (file, m->descriptor);
+       fprintf (file, "\",\n     ");
+       if ( (m->flags & ACC_STATIC) !=0)  fprintf (file, "true");
+                                     else fprintf (file, "false");
+       fprintf (file, ",\n     ");
+       fprintf (file, "(functionptr) ");
+       printID (m->class->name);
+       fprintf (file,"_");
+       printID (m->name);
+       fprintf (file,"\n   },\n");
+}
+
+
+
+
+
+static void headers_start ()
+{
+       file = fopen ("nativetypes.hh", "w");
+       if (!file) panic ("Can not open file 'native.h' to store header information");
+       
+       fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
+       fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
+
+       nativechain = chain_new ();
+}
+
+
+static void headers_finish ()
+{
+       methodinfo *m;
+       
+       fprintf (file, "\n/* Prototypes for native methods */\n\n");
+       
+       m = chain_first (nativechain);
+       while (m) {
+               dopadding=false;                
+               printmethod (m);
+               
+               m = chain_next (nativechain);
+               }
+
+
+       file = fopen ("nativetable.hh", "w");
+       if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
+
+       fprintf (file, "/* Table of native methods: nativetables.hh */\n");
+       fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
+
+       while ( (m = chain_first (nativechain)) != NULL) {
+               chain_remove (nativechain);
+               
+               printnativetableentry (m);
+               
+               }
+               
+       chain_free (nativechain);
+       fclose (file);
+}
+
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JAVA-Header-Generators auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+       printf ("USAGE: jch class [class..]\n");
+}   
+
+
+
+
+/************************** Funktion: main *******************************
+
+   Das Hauptprogramm.
+   Wird vom System zu Programstart aufgerufen (eh klar).
+   
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+       s4 i,a;
+       char *cp;
+       classinfo *topclass;
+       void *dummy;
+               
+
+   /********** interne (nur fuer main relevante Optionen) **************/
+   
+       char classpath[500] = "";
+       u4 heapsize = 100000;
+
+   /*********** Optionen, damit wirklich nur headers generiert werden ***/
+   
+   makeinitializations=false;
+   
+
+   /************ Infos aus der Environment lesen ************************/
+
+       cp = getenv ("CLASSPATH");
+       if (cp) {
+               strcpy (classpath + strlen(classpath), ":");
+               strcpy (classpath + strlen(classpath), cp);
+               }
+
+       if (argc < 2) {
+               print_usage ();
+               exit(10);
+               }
+
+
+   /**************************** Programmstart *****************************/
+
+       log_init (NULL);
+       log_text ("Java - header-generator started");
+       
+       
+       suck_init (classpath);
+       
+       unicode_init ();
+       heap_init (heapsize, heapsize, &dummy);
+       loader_init ();
+
+
+   /*********************** JAVA-Klassen laden  ***************************/
+   
+       headers_start ();
+
+       
+       for (a=1; a<argc; a++) {   
+               cp = argv[a];
+               for (i=strlen(cp)-1; i>=0; i--) {     /* Punkte im Klassennamen */
+                       if (cp[i]=='.') cp[i]='/';        /* auf slashes umbauen */
+                       }
+
+               topclass = loader_load ( unicode_new_char (cp) );
+               
+               headers_generate (topclass);
+               }
+       
+
+       headers_finish ();
+
+
+   /************************ Freigeben aller Resourcen *******************/
+
+       loader_close ();
+       heap_close ();
+       unicode_close (NULL);
+       
+
+   /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+       log_text ("Java - header-generator stopped");
+       log_cputime ();
+       mem_usagelog(1);
+       
+       return 0;
+}
+
+
diff --git a/loader.c b/loader.c
new file mode 100644 (file)
index 0000000..c94327c
--- /dev/null
+++ b/loader.c
@@ -0,0 +1,1994 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** loader.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the functions of the class loader.
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/06/03
+
+*******************************************************************************/
+
+
+#include <assert.h>
+
+#include "global.h"
+#include "loader.h"
+
+#include "tables.h"
+#include "native.h"
+#include "builtin.h"
+#include "compiler.h"
+#include "asmpart.h"
+
+#include "threads/thread.h"                        /* schani */
+
+
+/*************************** globale Variablen *******************************/
+
+extern bool newcompiler;               
+
+int count_class_infos = 0;
+int count_const_pool_len = 0;
+int count_vftbl_len = 0;
+int count_all_methods = 0;
+int count_vmcode_len = 0;
+int count_extable_len = 0;
+
+bool loadverbose = false;        /* Switches f"ur mehr Debug-Meldungen */
+bool linkverbose = false;
+bool initverbose = false;
+
+bool makeinitializations = true;
+
+bool getloadingtime = false;
+long int loadingtime = 0;
+
+
+static u4 interfaceindex;        /* fortlaufende Nummer f"ur Interfaces */ 
+
+static list unloadedclasses;     /* Liste alle referenzierten, aber noch nicht 
+                                    geladenen Klassen */
+static list unlinkedclasses;     /* Liste aller geladenen, aber noch nicht
+                                    gelinkten Klassen */ 
+       list linkedclasses;       /* Liste aller fertig gelinkten Klassen */
+
+
+
+/***************** die Referenzen auf die wichtigen Systemklassen ************/
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_ClassCastException;
+classinfo *class_java_lang_NullPointerException;
+classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+classinfo *class_java_lang_NegativeArraySizeException;
+classinfo *class_java_lang_OutOfMemoryError;
+classinfo *class_java_lang_ArithmeticException;
+classinfo *class_java_lang_ArrayStoreException;
+classinfo *class_java_lang_ThreadDeath;                 /* schani */
+
+classinfo *class_array;
+
+
+/************ einige vorgefertigte Instanzen wichtiger Systemklassen *********/
+
+java_objectheader *proto_java_lang_ClassCastException;
+java_objectheader *proto_java_lang_NullPointerException;
+java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+java_objectheader *proto_java_lang_NegativeArraySizeException;
+java_objectheader *proto_java_lang_OutOfMemoryError;
+java_objectheader *proto_java_lang_ArithmeticException;
+java_objectheader *proto_java_lang_ArrayStoreException;
+java_objectheader *proto_java_lang_ThreadDeath;         /* schani */
+
+
+
+
+/****************************************************************************/
+/******************* Einige Support-Funkionen *******************************/
+/****************************************************************************/
+
+
+/********** interne Funktion: printflags  (nur zu Debug-Zwecken) ************/
+
+static void printflags (u2 f)
+{
+   if ( f & ACC_PUBLIC )       printf (" PUBLIC");
+   if ( f & ACC_PRIVATE )      printf (" PRIVATE");
+   if ( f & ACC_PROTECTED )    printf (" PROTECTED");
+   if ( f & ACC_STATIC )       printf (" STATIC");
+   if ( f & ACC_FINAL )        printf (" FINAL");
+   if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
+   if ( f & ACC_VOLATILE )     printf (" VOLATILE");
+   if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
+   if ( f & ACC_NATIVE )       printf (" NATIVE");
+   if ( f & ACC_INTERFACE )    printf (" INTERFACE");
+   if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
+}
+
+
+/************************* Funktion: skipattribute ****************************
+
+       "uberliest im ClassFile eine (1) 'attribute'-Struktur 
+
+******************************************************************************/
+
+static void skipattribute ()
+{
+       u4 len;
+
+       suck_u2 ();
+       len = suck_u4 ();
+       skip_nbytes (len);      
+}
+
+/********************** Funktion: skipattributebody ***************************
+
+       "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
+       Referenz schon gelesen worden ist.
+       
+******************************************************************************/
+
+static void skipattributebody ()
+{
+       u4 len = suck_u4 ();
+       skip_nbytes (len);
+}
+
+
+/************************* Funktion: skipattributes ***************************
+
+       "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
+       
+******************************************************************************/
+
+static void skipattributes (u4 num)
+{
+       u4 i;
+       for (i=0; i<num; i++) skipattribute();
+}
+
+
+
+/************************** Funktion: loadUtf8 ********************************
+
+       liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text) 
+       und legt daf"ur ein unicode-Symbol an. 
+       Return: Zeiger auf das Symbol 
+
+******************************************************************************/
+
+#define MAXUNICODELEN 5000
+static u2 unicodebuffer[MAXUNICODELEN];
+
+static unicode *loadUtf8 ()
+{
+       u4 unicodelen;
+       u4 letter;
+
+       u4 utflen;
+       u4 b1,b2,b3;
+
+       unicodelen = 0;
+
+       utflen = suck_u2 ();
+       while (utflen > 0) {
+               b1 = suck_u1 ();
+               utflen --;
+               if (b1<0x80) letter = b1;
+               else {
+                       b2 = suck_u1 ();
+                       utflen --;
+                       if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
+                       else {
+                               b3 = suck_u1 ();
+                               utflen --;
+                               letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
+                               }
+                       }       
+       
+
+               if (unicodelen >= MAXUNICODELEN) {
+                       panic ("String constant too long");
+                       }
+               
+               unicodebuffer[unicodelen++] = letter;                   
+               }
+
+       
+       return unicode_new_u2 (unicodebuffer, unicodelen);
+}
+
+
+
+/******************** interne Funktion: checkfieldtype ***********************/
+
+static void checkfieldtype (u2 *text, u4 *count, u4 length)
+{
+       u4 l;
+
+       if (*count >= length) panic ("Type-descriptor exceeds unicode length");
+       
+       l = text[(*count)++];
+       
+       switch (l) {
+               default: panic ("Invalid symbol in type descriptor");
+                        return;
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'F':
+               case 'I':
+               case 'J':
+               case 'S':
+               case 'Z': return;
+               
+               case '[': checkfieldtype (text, count, length);
+                         return;
+                         
+               case 'L': 
+                       {
+                       u4 tlen,tstart = *count;
+                       
+                       if (*count >= length) 
+                          panic ("Objecttype descriptor of length zero");
+                       
+                       while ( text[*count] != ';' ) {
+                               (*count)++;
+                               if (*count >= length) 
+                                  panic ("Missing ';' in objecttype-descriptor");
+                               }
+                       
+                       tlen = (*count) - tstart;
+                       (*count)++;
+
+                       if (tlen == 0) panic ("Objecttype descriptor with empty name");
+                                       
+                       class_get ( unicode_new_u2 (text+tstart, tlen) );
+                       }
+               }       
+}
+
+
+/******************* Funktion: checkfielddescriptor ***************************
+
+       "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
+       Wenn nicht, dann wird das System angehalten.
+       Au"serdem werden alle Klassen, die hier referenziert werden, 
+       in die Liste zu ladender Klassen eingetragen.
+       
+******************************************************************************/
+
+void checkfielddescriptor (unicode *d)
+{
+       u4 count=0;
+       checkfieldtype (d->text, &count, d->length);
+       if (count != d->length) panic ("Invalid type-descritor encountered");
+}
+
+
+/******************* Funktion: checkmethoddescriptor **************************
+
+       "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
+       Wenn nicht, dann wird das System angehalten.
+       Au"serdem werden alle Klassen, die hier referenziert werden, 
+       in die Liste zu ladender Klassen eingetragen.
+       
+******************************************************************************/
+
+void checkmethoddescriptor (unicode *d)
+{
+       u2 *text=d->text;
+       u4 length=d->length;
+       u4 count=0;
+       
+       if (length<2) panic ("Method descriptor too short");
+       if (text[0] != '(') panic ("Missing '(' in method descriptor");
+       count=1;
+       
+       while (text[count] != ')') {
+               checkfieldtype (text,&count,length);
+               if ( count > length-2 ) panic ("Unexpected end of descriptor");
+               }
+               
+       count++;
+       if (text[count] == 'V') count++;
+       else                    checkfieldtype (text, &count,length);
+               
+       if (count != length) panic ("Method-descriptor has exceeding chars");
+}
+
+
+/******************** Funktion: buildarraydescriptor ****************************
+
+       erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
+       entsprechende constant_arraydescriptor - Struktur 
+       
+********************************************************************************/
+
+static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
+{
+       constant_arraydescriptor *d;
+       
+       if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
+       d = NEW (constant_arraydescriptor);
+       d -> objectclass = NULL;
+       d -> elementdescriptor = NULL;
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_arraydescriptor);
+#endif
+
+       switch (name[1]) {
+       case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
+       case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
+       case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
+       case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
+       case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
+       case 'I': d -> arraytype = ARRAYTYPE_INT; break;
+       case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
+       case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
+
+       case '[':
+               d -> arraytype = ARRAYTYPE_ARRAY; 
+               d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
+               break;
+               
+       case 'L':
+               d -> arraytype = ARRAYTYPE_OBJECT;
+               d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
+               break;
+       }
+       return d;
+}
+
+
+/******************* Funktion: freearraydescriptor ****************************
+
+       entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
+       aus dem Speicher
+       
+*******************************************************************************/
+
+static void freearraydescriptor (constant_arraydescriptor *d)
+{
+       while (d) {
+               constant_arraydescriptor *n = d->elementdescriptor;
+               FREE (d, constant_arraydescriptor);
+               d = n;
+               }
+}
+
+/*********************** Funktion: displayarraydescriptor *********************/
+
+static void displayarraydescriptor (constant_arraydescriptor *d)
+{
+       switch (d->arraytype) {
+       case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
+       case ARRAYTYPE_BYTE: printf ("byte[]"); break;
+       case ARRAYTYPE_CHAR: printf ("char[]"); break;
+       case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
+       case ARRAYTYPE_FLOAT: printf ("float[]"); break;
+       case ARRAYTYPE_INT: printf ("int[]"); break;
+       case ARRAYTYPE_LONG: printf ("long[]"); break;
+       case ARRAYTYPE_SHORT: printf ("short[]"); break;
+       case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
+       case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
+       }
+}
+
+
+
+/*****************************************************************************/
+/******************** Funktionen fuer Fields *********************************/
+/*****************************************************************************/
+
+
+/************************ Funktion: field_load ********************************
+
+       l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
+       und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
+       Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
+       reserviert.
+
+******************************************************************************/
+
+static void field_load (fieldinfo *f, classinfo *c)
+{
+       u4 attrnum,i;
+       u4 jtype;
+
+       f -> flags = suck_u2 ();
+       f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       f -> type = jtype = desc_to_type (f->descriptor);
+       f -> offset = 0;
+
+       switch (f->type) {
+       case TYPE_INT:        f->value.i = 0; break;
+       case TYPE_FLOAT:      f->value.f = 0.0; break;
+       case TYPE_DOUBLE:     f->value.d = 0.0; break;
+       case TYPE_ADDRESS:    f->value.a = NULL; 
+                             heap_addreference (&(f->value.a));
+                             break;
+       case TYPE_LONG:
+#if U8_AVAILABLE
+               f->value.l = 0; break;
+#else
+               f->value.l.low = 0; f->value.l.high = 0; break;
+#endif 
+       }
+       
+       attrnum = suck_u2();
+       for (i=0; i<attrnum; i++) {
+               u4 pindex;
+               unicode *aname;
+
+               aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+               if ( aname != unicode_new_char ("ConstantValue") ) {
+                       skipattributebody ();
+                       }
+               else {
+                       suck_u4();
+                       pindex = suck_u2();
+                               
+                       switch (jtype) {
+                               case TYPE_INT: {
+                                       constant_integer *ci = 
+                                               class_getconstant(c, pindex, CONSTANT_Integer);
+                                       f->value.i = ci -> value;
+                                       }
+                                       break;
+                                       
+                               case TYPE_LONG: {
+                                       constant_long *cl = 
+                                          class_getconstant(c, pindex, CONSTANT_Long);
+       
+                                       f->value.l = cl -> value;
+                                       }
+                                       break;
+
+                               case TYPE_FLOAT: {
+                                       constant_float *cf = 
+                                           class_getconstant(c, pindex, CONSTANT_Float);
+       
+                                       f->value.f = cf->value;
+                                       }
+                                       break;
+                                                                                       
+                               case TYPE_DOUBLE: {
+                                       constant_double *cd = 
+                                           class_getconstant(c, pindex, CONSTANT_Double);
+       
+                                       f->value.d = cd->value;
+                                       }
+                                       break;
+                                               
+                               case TYPE_ADDRESS: {
+                                       unicode *u = 
+                                               class_getconstant(c, pindex, CONSTANT_String);
+                                       f->value.a = literalstring_new(u);
+                                       }
+                                       break;
+       
+                               default: 
+                                       log_text ("Invalid Constant - Type");
+
+                               }
+
+                       }
+               }
+               
+}
+
+
+/********************** Funktion: field_free *********************************/
+
+static void field_free (fieldinfo *f)
+{
+}
+
+
+/************** Funktion: field_display (nur zu Debug-Zwecken) ***************/
+
+static void field_display (fieldinfo *f)
+{
+       printf ("   ");
+       printflags (f -> flags);
+       printf (" ");
+       unicode_display (f -> name);
+       printf (" ");
+       unicode_display (f -> descriptor);      
+       printf (" offset: %ld\n", (long int) (f -> offset) );
+}
+
+
+
+
+/*****************************************************************************/
+/************************* Funktionen f"ur Methods ***************************/ 
+/*****************************************************************************/
+
+
+/*********************** Funktion: method_load ********************************
+
+       l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
+       eine schon existierende 'methodinfo'-Struktur aus.
+       Bei allen native-Methoden wird au"serdem gleich der richtige 
+       Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
+       Zeiger auf den Compiler 
+       
+******************************************************************************/
+
+static void method_load (methodinfo *m, classinfo *c)
+{
+       u4 attrnum,i,e;
+       
+#ifdef STATISTICS
+       count_all_methods++;
+#endif
+
+       m -> class = c;
+       
+       m -> flags = suck_u2 ();
+       m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       
+       m -> jcode = NULL;
+       m -> exceptiontable = NULL;
+       m -> entrypoint = NULL;
+       m -> mcode = NULL;
+       m -> stubroutine = NULL;
+       
+       if (! (m->flags & ACC_NATIVE) ) {
+               m -> stubroutine = createcompilerstub (m);
+               }
+       else {
+               functionptr f = native_findfunction 
+                      (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
+               if (f) {
+               if (newcompiler)
+                       m -> stubroutine = ncreatenativestub (f, m);
+               else
+                       m -> stubroutine = createnativestub (f, m);
+                       }
+               }
+       
+       
+       attrnum = suck_u2();
+       for (i=0; i<attrnum; i++) {
+               unicode *aname;
+
+               aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+               if ( aname != unicode_new_char("Code"))  {
+                       skipattributebody ();
+                       }
+               else {
+                       if (m -> jcode) panic ("Two code-attributes for one method!");
+                       
+                       suck_u4();
+                       m -> maxstack = suck_u2();
+                       m -> maxlocals = suck_u2();
+                       m -> jcodelength = suck_u4();
+                       m -> jcode = MNEW (u1, m->jcodelength);
+                       suck_nbytes (m->jcode, m->jcodelength);
+                       m -> exceptiontablelength = suck_u2 ();
+                       m -> exceptiontable = 
+                          MNEW (exceptiontable, m->exceptiontablelength);
+
+#ifdef STATISTICS
+       count_vmcode_len += m->jcodelength + 18;
+       count_extable_len += 8 * m->exceptiontablelength;
+#endif
+
+                       for (e=0; e < m->exceptiontablelength; e++) {
+                               u4 idx;
+                               m -> exceptiontable[e].startpc = suck_u2();
+                               m -> exceptiontable[e].endpc = suck_u2();
+                               m -> exceptiontable[e].handlerpc = suck_u2();
+
+                               idx = suck_u2();
+                               if (!idx) m -> exceptiontable[e].catchtype = NULL;
+                               else {
+                                       m -> exceptiontable[e].catchtype = 
+                                     class_getconstant (c, idx, CONSTANT_Class);
+                                       }
+                               }                       
+
+                       skipattributes ( suck_u2() );
+                       }
+                       
+               }
+
+
+}
+
+
+/********************* Funktion: method_free **********************************
+
+       gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
+       wieder frei
+
+******************************************************************************/
+
+static void method_free (methodinfo *m)
+{
+       if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
+       if (m->exceptiontable) 
+               MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
+       if (m->mcode) CFREE (m->mcode, m->mcodelength);
+       if (m->stubroutine) {
+               if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
+               else                       removecompilerstub (m->stubroutine);
+               }
+}
+
+
+/************** Funktion: method_display  (nur zu Debug-Zwecken) *************/
+
+void method_display (methodinfo *m)
+{
+       printf ("   ");
+       printflags (m -> flags);
+       printf (" ");
+       unicode_display (m -> name);
+       printf (" "); 
+       unicode_display (m -> descriptor);
+       printf ("\n");
+}
+
+
+/******************** Funktion: method_canoverwrite ***************************
+
+       "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
+       ist (also mit einer Methodendefinition eine andere "uberschrieben 
+       werden kann).
+       
+******************************************************************************/  
+
+static bool method_canoverwrite (methodinfo *m, methodinfo *old)
+{
+       if (m->name != old->name) return false;
+       if (m->descriptor != old->descriptor) return false;
+       if (m->flags & ACC_STATIC) return false;
+       return true;
+}
+
+
+
+
+/*****************************************************************************/
+/************************ Funktionen fuer Class ******************************/
+/*****************************************************************************/
+
+
+/******************** Funktion: class_get *************************************
+
+       Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
+       eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
+       ladenen Klassen ein).
+
+******************************************************************************/
+
+classinfo *class_get (unicode *u)
+{
+       classinfo *c;
+       
+       if (u->class) return u->class;
+       
+#ifdef STATISTICS
+       count_class_infos += sizeof(classinfo);
+#endif
+
+       c = NEW (classinfo);
+       c -> flags = 0;
+       c -> name = u;
+       c -> cpcount = 0;
+       c -> cptags = NULL;
+       c -> cpinfos = NULL;
+       c -> super = NULL;
+       c -> interfacescount = 0;
+       c -> interfaces = NULL;
+       c -> fieldscount = 0;
+       c -> fields = NULL;
+       c -> methodscount = 0;
+       c -> methods = NULL;
+       c -> linked = false;
+       c -> index = 0;
+       c -> instancesize = 0;
+       c -> vftbl = NULL;
+       c -> initialized = false;
+       
+       unicode_setclasslink (u,c);
+       list_addlast (&unloadedclasses, c);
+               
+       return c;
+}
+
+
+
+/******************** Funktion: class_getconstant *****************************
+
+       holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
+       Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
+
+******************************************************************************/
+
+voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
+{
+       if (pos >= c->cpcount) 
+               panic ("Attempt to access constant outside range");
+       if (c->cptags[pos] != ctype) {
+               sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
+                (int) ctype, (int) c->cptags[pos] );
+               error();
+               }
+               
+       return c->cpinfos[pos];
+}
+
+
+/********************* Funktion: class_constanttype ***************************
+
+       Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
+       Klasse hat.
+       
+******************************************************************************/
+
+u4 class_constanttype (classinfo *c, u4 pos)
+{
+       if (pos >= c->cpcount) 
+               panic ("Attempt to access constant outside range");
+       return c->cptags[pos];
+}
+
+
+/******************** Funktion: class_loadcpool *******************************
+
+       l"adt den gesammten ConstantPool einer Klasse.
+       
+       Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers 
+       Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
+       F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h' 
+
+******************************************************************************/
+
+static void class_loadcpool (classinfo *c)
+{
+
+       typedef struct forward_class {      /* Diese Strukturen dienen dazu, */
+               struct forward_class *next;     /* die Infos, die beim ersten */
+               u2 thisindex;                   /* Durchgang durch den ConstantPool */
+               u2 name_index;                  /* gelesen werden, aufzunehmen. */
+       } forward_class;                    /* Erst nachdem der ganze Pool */ 
+                                        /* gelesen wurde, k"onnen alle */
+       typedef struct forward_string {     /* Felder kompletiert werden */
+               struct forward_string *next;    /* (und das auch nur in der richtigen */
+               u2 thisindex;                   /* Reihenfolge) */
+               u2 string_index;
+       } forward_string;
+
+       typedef struct forward_nameandtype {
+               struct forward_nameandtype *next;
+               u2 thisindex;
+               u2 name_index;
+               u2 sig_index;
+       } forward_nameandtype;
+
+       typedef struct forward_fieldmethint {   
+               struct forward_fieldmethint *next;
+               u2 thisindex;
+               u1 tag;
+               u2 class_index;
+               u2 nameandtype_index;
+       } forward_fieldmethint;
+
+
+
+       u4 idx;
+       long int dumpsize = dump_size ();
+
+       forward_class *forward_classes = NULL;
+       forward_string *forward_strings = NULL;
+       forward_nameandtype *forward_nameandtypes = NULL;
+       forward_fieldmethint *forward_fieldmethints = NULL;
+
+       u4 cpcount       = c -> cpcount = suck_u2();
+       u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
+       voidptr *cpinfos = c -> cpinfos =  MNEW (voidptr, cpcount);
+
+#ifdef STATISTICS
+       count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#endif
+
+       
+       for (idx=0; idx<cpcount; idx++) {
+               cptags[idx] = CONSTANT_UNUSED;
+               cpinfos[idx] = NULL;
+               }
+
+                       
+               /******* Erster Durchgang *******/
+               /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen, 
+                  werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
+                  und dann am Ende nocheinmal durchgegangen */
+
+       idx = 1;
+       while (idx < cpcount) {
+               u4 t = suck_u1 ();
+               switch ( t ) {
+
+                       case CONSTANT_Class: { 
+                               forward_class *nfc = DNEW(forward_class);
+
+                               nfc -> next = forward_classes;                                                                                  
+                               forward_classes = nfc;
+
+                               nfc -> thisindex = idx;
+                               nfc -> name_index = suck_u2 ();
+
+                               idx++;
+                               break;
+                               }
+                       
+                       case CONSTANT_Fieldref:
+                       case CONSTANT_Methodref:
+                       case CONSTANT_InterfaceMethodref: {
+                               forward_fieldmethint *nff = DNEW (forward_fieldmethint);
+                               
+                               nff -> next = forward_fieldmethints;
+                               forward_fieldmethints = nff;
+
+                               nff -> thisindex = idx;
+                               nff -> tag = t;
+                               nff -> class_index = suck_u2 ();
+                               nff -> nameandtype_index = suck_u2 ();
+
+                               idx ++;                                         
+                               break;
+                               }
+                               
+                       case CONSTANT_String: {
+                               forward_string *nfs = DNEW (forward_string);
+                               
+                               nfs -> next = forward_strings;
+                               forward_strings = nfs;
+                               
+                               nfs -> thisindex = idx;
+                               nfs -> string_index = suck_u2 ();
+                               
+                               idx ++;
+                               break;
+                               }
+
+                       case CONSTANT_NameAndType: {
+                               forward_nameandtype *nfn = DNEW (forward_nameandtype);
+                               
+                               nfn -> next = forward_nameandtypes;
+                               forward_nameandtypes = nfn;
+                               
+                               nfn -> thisindex = idx;
+                               nfn -> name_index = suck_u2 ();
+                               nfn -> sig_index = suck_u2 ();
+                               
+                               idx ++;
+                               break;
+                               }
+
+                       case CONSTANT_Integer: {
+                               constant_integer *ci = NEW (constant_integer);
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_integer);
+#endif
+
+                               ci -> value = suck_s4 ();
+                               cptags [idx] = CONSTANT_Integer;
+                               cpinfos [idx] = ci;
+                               idx ++;
+                               
+                               break;
+                               }
+                               
+                       case CONSTANT_Float: {
+                               constant_float *cf = NEW (constant_float);
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_float);
+#endif
+
+                               cf -> value = suck_float ();
+                               cptags [idx] = CONSTANT_Float;
+                               cpinfos[idx] = cf;
+                               idx ++;
+                               break;
+                               }
+                               
+                       case CONSTANT_Long: {
+                               constant_long *cl = NEW(constant_long);
+                                       
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_long);
+#endif
+
+                               cl -> value = suck_s8 ();
+                               cptags [idx] = CONSTANT_Long;
+                               cpinfos [idx] = cl;
+                               idx += 2;
+                               break;
+                               }
+                       
+                       case CONSTANT_Double: {
+                               constant_double *cd = NEW(constant_double);
+                               
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_double);
+#endif
+
+                               cd -> value = suck_double ();
+                               cptags [idx] = CONSTANT_Double;
+                               cpinfos [idx] = cd;
+                               idx += 2;
+                               break;
+                               }
+                               
+                       case CONSTANT_Utf8: {
+                               unicode *u;
+
+                               u = loadUtf8 ();
+
+                               cptags [idx] = CONSTANT_Utf8;
+                               cpinfos [idx] = u;
+                               idx++;
+                               break;
+                               }
+                                                                               
+                       default:
+                               sprintf (logtext, "Unkown constant type: %d",(int) t);
+                               error ();
+               
+                       }  /* end switch */
+                       
+               } /* end while */
+               
+
+
+          /* Aufl"osen der noch unfertigen Eintr"age */
+
+       while (forward_classes) {
+               unicode *name =
+                 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
+               
+               if ( (name->length>0) && (name->text[0]=='[') ) {
+                       checkfielddescriptor (name); 
+
+                       cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
+                       cpinfos [forward_classes -> thisindex] = 
+                          buildarraydescriptor(name->text, name->length);
+
+                       }
+               else {          
+                       cptags  [forward_classes -> thisindex] = CONSTANT_Class;
+                       cpinfos [forward_classes -> thisindex] = class_get (name);
+                       }
+               forward_classes = forward_classes -> next;
+               
+               }
+
+       while (forward_strings) {
+               unicode *text = 
+                 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
+                       
+               cptags   [forward_strings -> thisindex] = CONSTANT_String;
+               cpinfos  [forward_strings -> thisindex] = text;
+               
+               forward_strings = forward_strings -> next;
+               }       
+
+       while (forward_nameandtypes) {
+               constant_nameandtype *cn = NEW (constant_nameandtype);  
+
+#ifdef STATISTICS
+               count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+               cn -> name = class_getconstant 
+                  (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
+               cn -> descriptor = class_getconstant
+                  (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
+                
+               cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
+               cpinfos  [forward_nameandtypes -> thisindex] = cn;
+               
+               forward_nameandtypes = forward_nameandtypes -> next;
+               }
+
+
+       while (forward_fieldmethints)  {
+               constant_nameandtype *nat;
+               constant_FMIref *fmi = NEW (constant_FMIref);
+
+#ifdef STATISTICS
+               count_const_pool_len += sizeof(constant_FMIref);
+#endif
+
+               nat = class_getconstant
+                       (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
+
+               fmi -> class = class_getconstant 
+                       (c, forward_fieldmethints -> class_index, CONSTANT_Class);
+               fmi -> name = nat -> name;
+               fmi -> descriptor = nat -> descriptor;
+
+               cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
+               cpinfos [forward_fieldmethints -> thisindex] = fmi;
+       
+               switch (forward_fieldmethints -> tag) {
+               case CONSTANT_Fieldref:  checkfielddescriptor (fmi->descriptor);
+                                        break;
+               case CONSTANT_InterfaceMethodref: 
+               case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
+                                        break;
+               }               
+       
+               forward_fieldmethints = forward_fieldmethints -> next;
+
+               }
+
+
+       dump_release (dumpsize);
+}
+
+
+/********************** Funktion: class_load **********************************
+
+       l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
+       'classinfo'-Struktur mu"s bereits angelegt worden sein.
+       
+       Die Superklasse und die Interfaces, die diese Klasse implementiert,
+       m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
+       Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
+       
+       Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
+       und in die Liste 'unlinkedclasses' eingh"angt.
+       
+******************************************************************************/
+
+static void class_load (classinfo *c)
+{
+       u4 i;
+       u4 mi,ma;
+
+
+       if (loadverbose) {
+               sprintf (logtext, "Loading class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name );
+               dolog();
+               }
+
+
+       suck_start (c->name);
+
+       if (suck_u4() != MAGIC) panic("Can not find class-file signature");   
+       mi = suck_u2(); 
+       ma = suck_u2();
+       if (ma != MAJOR_VERSION) {
+               sprintf (logtext, "Can only support major version %d, but not %d",
+                                MAJOR_VERSION, (int) ma);
+               error();
+               }
+       if (mi > MINOR_VERSION)  {
+               sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
+               error();
+               }
+
+
+       class_loadcpool (c);
+       
+       c -> flags = suck_u2 ();
+       suck_u2 ();       /* this */
+       
+       if ( (i = suck_u2 () ) ) {
+               c -> super = class_getconstant (c, i, CONSTANT_Class);
+               }
+       else {
+               c -> super = NULL;
+               }
+                        
+       c -> interfacescount = suck_u2 ();
+       c -> interfaces = MNEW (classinfo*, c -> interfacescount);
+       for (i=0; i < c -> interfacescount; i++) {
+               c -> interfaces [i] = 
+                     class_getconstant (c, suck_u2(), CONSTANT_Class);
+               }
+
+       c -> fieldscount = suck_u2 ();
+       c -> fields = MNEW (fieldinfo, c -> fieldscount);
+       for (i=0; i < c -> fieldscount; i++) {
+               field_load (&(c->fields[i]), c);
+               }
+
+       c -> methodscount = suck_u2 ();
+       c -> methods = MNEW (methodinfo, c -> methodscount);
+       for (i=0; i < c -> methodscount; i++) {
+               method_load (&(c -> methods [i]), c);
+               }
+
+#ifdef STATISTICS
+       count_class_infos += sizeof(classinfo*) * c -> interfacescount;
+       count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
+       count_class_infos += sizeof(methodinfo) * c -> methodscount;
+#endif
+
+
+       skipattributes ( suck_u2() );
+
+
+       suck_stop ();
+
+       list_remove (&unloadedclasses, c);
+       list_addlast (&unlinkedclasses, c);
+}
+
+
+
+/************** interne Funktion: class_highestinterface **********************
+
+       wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
+       die Interfacetable einer Klasse sein mu"s.
+
+******************************************************************************/
+
+static s4 class_highestinterface (classinfo *c) 
+{
+       s4 h;
+       s4 i;
+       
+       if ( ! (c->flags & ACC_INTERFACE) ) {
+               sprintf (logtext, "Interface-methods count requested for non-interface:  ");
+       unicode_sprint (logtext+strlen(logtext), c->name);
+       error();
+       }
+    
+    h = c->index;
+       for (i=0; i<c->interfacescount; i++) {
+               s4 h2 = class_highestinterface (c->interfaces[i]);
+               if (h2>h) h=h2;
+               }
+       return h;
+}
+
+
+/**************** Funktion: class_addinterface ********************************
+
+       wird von der Funktion class_link ben"otigt, um eine Virtual Function 
+       Table f"ur ein Interface (und alle weiteren von diesem Interface
+       implementierten Interfaces) in eine Klasse einzutragen.
+
+******************************************************************************/        
+
+static void class_addinterface (classinfo *c, classinfo *ic)
+{
+       u4 i = ic->index;
+       u4 j,m;
+       vftbl *vftbl = c->vftbl;
+       
+       if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
+       if (vftbl->interfacevftbl[i]) return;
+
+       if (ic->methodscount==0) {  /* wenn interface keine Methoden hat, dann 
+                                      trotzdem eine Tabelle mit L"ange 1 anlegen,
+                                      wegen Subclass-Tests */
+               vftbl -> interfacevftbllength[i] = 1;
+               vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
+               vftbl -> interfacevftbl[i][0] = NULL;
+               }
+       else {
+               vftbl -> interfacevftbllength[i] = ic -> methodscount;
+               vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount); 
+
+#ifdef STATISTICS
+       count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
+#endif
+
+               for (j=0; j<ic->methodscount; j++) {
+                       classinfo *sc = c;
+                       while (sc) {
+                               for (m=0; m<sc->methodscount; m++) {
+                                       methodinfo *mi = &(sc->methods[m]);
+                                       if (method_canoverwrite (mi, &(ic->methods[j])) ) {
+                                               vftbl->interfacevftbl[i][j] = 
+                                                        vftbl->table[mi->vftblindex];
+                                               goto foundmethod;
+                                               }
+                                       }
+                               sc = sc->super;
+                               }
+                        foundmethod: ;
+                       }
+               }
+               
+       for (j=0; j<ic->interfacescount; j++) 
+               class_addinterface(c, ic->interfaces[j]);
+}
+
+
+/********************** Funktion: class_link **********************************
+
+       versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
+       m"ussen sowol die Superklasse, als auch alle implementierten
+       Interfaces schon gelinkt sein.
+       Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
+       dieser Klasse, als auch die Virtual Function Tables f"ur normale
+       Methoden als auch Interface-Methoden.
+       
+       Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
+       der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
+       eingetragen.
+       Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
+
+       Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
+                eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
+
+******************************************************************************/
+
+static void class_link (classinfo *c)
+{
+       u4 supervftbllength;          /* L"ange der VFTBL der Superklasse */
+       u4 vftbllength;               /* L"ange der VFTBL dieser Klasse */
+       classinfo *super = c->super;  
+       classinfo *ic,*c2;            /* Hilfsvariablen */
+       vftbl *v;
+       u4 i;                          
+
+
+               /* schauen, ob alle "ubergeordneten Klassen schon fertig sind, 
+                  und richtiges Initialisieren der lokalen Variablen */ 
+
+       for ( i=0; i<c->interfacescount; i++) {
+               ic = c->interfaces[i];
+               if ( !ic -> linked) {
+                       list_remove (&unlinkedclasses,c );
+                       list_addlast (&unlinkedclasses,c );
+                       return; 
+                       }
+               }
+       
+       if (! super) {
+               c -> index = 0;
+               c -> instancesize = sizeof (java_objectheader);
+               
+               vftbllength = supervftbllength = 0;
+
+               c -> finalizer = NULL;
+               }
+       else {
+               if ( !super -> linked ) {
+                       list_remove (&unlinkedclasses,c );
+                       list_addlast (&unlinkedclasses,c );
+                       return; 
+                       }
+
+               if ( c->flags & ACC_INTERFACE)     c -> index = interfaceindex++;
+                                       else       c -> index = super -> index + 1;
+               
+               c -> instancesize = super -> instancesize;
+               
+               vftbllength = supervftbllength = super -> vftbl -> vftbllength;
+               
+               c -> finalizer = super -> finalizer;
+               }
+
+
+       if (linkverbose) {
+               sprintf (logtext, "Linking Class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name );
+               dolog ();
+               }
+
+               /* Erstellen der Virtual Function Table */
+
+       for (i=0; i < c->methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+                       
+               if (! (m->flags & ACC_STATIC) ) {
+                       classinfo *sc = super;
+                       while (sc) {
+                               int j;
+                               for (j=0; j < sc->methodscount; j++) {
+                                       if ( method_canoverwrite (m, &(sc->methods[j])) ) {
+                                               m -> vftblindex = sc->methods[j].vftblindex;
+                                               goto foundvftblindex;
+                                               }
+                                       }
+                               sc = sc->super;
+                               }
+                       m -> vftblindex = (vftbllength++);
+                 foundvftblindex: ;
+                       }
+               }       
+       
+#ifdef STATISTICS
+       count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
+#endif
+
+       c -> vftbl = v = (vftbl*) 
+            mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
+       v -> class = c;
+       v -> vftbllength = vftbllength;
+       v -> interfacetablelength = 0;
+       
+       for (i=0; i < supervftbllength; i++) 
+          v -> table[i] = super -> vftbl -> table[i];
+       
+       for (i=0; i < c->methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+               if ( ! (m->flags & ACC_STATIC) ) {
+                       v -> table[m->vftblindex] = m -> stubroutine;
+                       }
+               }
+
+
+               /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen 
+                  Felder */
+       
+       for (i=0; i < c->fieldscount; i++) {
+               u4 dsize;
+               fieldinfo *f = &(c -> fields[i]);
+               
+               if ( ! (f->flags & ACC_STATIC) ) {
+                       dsize = desc_typesize (f->descriptor);
+                       c -> instancesize = ALIGN ( c->instancesize, dsize);
+                       f -> offset = c -> instancesize;
+                       c -> instancesize += dsize;
+                       }
+
+               }
+
+       
+               /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
+       
+       c2 = c;
+       while (c2) {
+               for (i=0; i<c2->interfacescount; i++) {
+                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+                       if ( h > v->interfacetablelength) v->interfacetablelength = h;
+                       }
+               c2 = c2->super;
+               }
+       v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
+       v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength); 
+
+#ifdef STATISTICS
+       count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
+#endif
+
+       for (i=0; i < v->interfacetablelength; i++) {
+               v -> interfacevftbllength[i] = 0;
+               v -> interfacevftbl[i] = NULL;
+               }
+       
+       c2 = c;
+       while (c2) {
+               for (i=0; i<c2->interfacescount; i++) {
+                       class_addinterface (c, c2->interfaces[i]);
+                       }
+               c2 = c2->super;
+               }
+               
+
+
+               /* Die finalizer-Methode suchen und eintragen (wenn vorhanden), 
+                  aber nur bei Objekten ausser java.lang.Object */
+
+       if (super) {
+               methodinfo *fi;
+               static unicode *finame=NULL,*fidesc=NULL;
+               
+               if (!finame) finame = unicode_new_char ("finalize");
+               if (!fidesc) fidesc = unicode_new_char ("()V");
+
+               fi = class_findmethod (c, finame, fidesc);
+               if (fi) {
+                       if (! (fi->flags & ACC_STATIC) ) {
+                               c -> finalizer = fi;
+                               }
+                       }
+       }
+       
+       
+               /* Abschlie"sende Aktionen */
+       
+       c -> linked = true;     
+
+       list_remove (&unlinkedclasses, c);
+       list_addlast (&linkedclasses, c);
+}
+
+
+/******************* Funktion: class_freepool *********************************
+
+       Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
+       wieder frei.
+
+******************************************************************************/
+
+static void class_freecpool (classinfo *c)
+{
+       u4 idx;
+       u4 tag;
+       voidptr info;
+       
+       for (idx=0; idx < c->cpcount; idx++) {
+               tag = c->cptags[idx];
+               info = c->cpinfos[idx];
+               
+               if (info != NULL) {
+                       switch (tag) {
+                       case CONSTANT_Fieldref:
+                       case CONSTANT_Methodref:
+                       case CONSTANT_InterfaceMethodref:
+                               FREE (info, constant_FMIref);
+                               break;
+                       case CONSTANT_Integer:
+                               FREE (info, constant_integer);
+                               break;
+                       case CONSTANT_Float:
+                               FREE (info, constant_float);
+                               break;
+                       case CONSTANT_Long:
+                               FREE (info, constant_long);
+                               break;
+                       case CONSTANT_Double:
+                               FREE (info, constant_double);
+                               break;
+                       case CONSTANT_NameAndType:
+                               FREE (info, constant_nameandtype);
+                               break;
+                       case CONSTANT_Arraydescriptor:
+                               freearraydescriptor (info);
+                               break;
+                       }
+                       }
+               }
+
+       MFREE (c -> cptags,  u1, c -> cpcount);
+       MFREE (c -> cpinfos, voidptr, c -> cpcount);
+}
+
+
+/*********************** Funktion: class_free *********************************
+
+       Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
+
+******************************************************************************/
+
+static void class_free (classinfo *c)
+{
+       u4 i;
+       vftbl *v;
+               
+       unicode_unlinkclass (c->name);
+       
+       class_freecpool (c);
+
+       MFREE (c->interfaces, classinfo*, c->interfacescount);
+
+       for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
+       MFREE (c->fields, fieldinfo, c->fieldscount);
+       
+       for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
+       MFREE (c->methods, methodinfo, c->methodscount);
+
+       if ( (v = c->vftbl) ) {
+               for (i=0; i<v->interfacetablelength; i++) {
+                       MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
+                       }
+               MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
+               MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
+
+               mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
+               }
+               
+       FREE (c, classinfo);
+}
+
+
+/************************* Funktion: class_findfield *************************
+       
+       sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
+       Namen und Typ.
+
+*****************************************************************************/
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
+{
+       u4 i;
+       for (i=0; i < c->fieldscount; i++) {
+               if ( (c->fields[i].name == name)  &&  (c->fields[i].descriptor == desc) )
+                       return &(c->fields[i]);
+               }
+       panic ("Can not find field given in CONSTANT_Fieldref");
+       return NULL;
+}
+
+
+/************************* Funktion: class_findmethod *************************
+       
+       sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
+       Namen und Typ.
+       Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
+
+*****************************************************************************/
+
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
+{
+       u4 i;
+       for (i=0; i < c->methodscount; i++) {
+               if (     (c->methods[i].name == name)  
+                         && (    (desc == NULL) 
+                             ||  (c->methods[i].descriptor == desc) 
+                            )  
+                  )
+                       return &(c->methods[i]);
+               }
+       return NULL;
+}
+
+
+/************************* Funktion: class_resolvemethod *************************
+       
+       sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
+
+*****************************************************************************/
+
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
+{
+       while (c) {
+               methodinfo *m = class_findmethod (c, name, desc);
+               if (m) return m;
+               c = c->super;
+               }
+       return NULL;
+}
+       
+
+
+/************************* Funktion: class_issubclass ************************
+
+       "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
+       
+*****************************************************************************/
+
+bool class_issubclass (classinfo *sub, classinfo *super)
+{
+       for (;;) {
+               if (!sub) return false;
+               if (sub==super) return true;
+               sub = sub -> super;
+               }
+}
+
+
+
+/****************** Initialisierungsfunktion f"ur eine Klasse ****************
+
+       In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
+       Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
+       Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
+       wird.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+extern int blockInts;
+#endif
+
+void class_init (classinfo *c)
+{
+       methodinfo *m;
+       java_objectheader *exceptionptr;
+       s4 i;
+       int b;
+
+       if (!makeinitializations) return;
+       if (c->initialized) return;
+       c -> initialized = true;
+       
+       if (c->super) class_init (c->super);
+       for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
+
+       m = class_findmethod (c, 
+                             unicode_new_char ("<clinit>"), 
+                             unicode_new_char ("()V"));
+       if (!m) {
+               if (initverbose) {
+                       sprintf (logtext, "Class ");
+                       unicode_sprint (logtext+strlen(logtext), c->name);
+                       sprintf (logtext+strlen(logtext), " has no initializer");       
+                       dolog ();
+                       }
+               return;
+               }
+               
+       if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
+       
+       if (initverbose) {
+               sprintf (logtext, "Starting initializer for class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name);
+               dolog ();
+       }
+
+#ifdef USE_THREADS
+       b = blockInts;
+       blockInts = 0;
+#endif
+
+       exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
+
+#ifdef USE_THREADS
+       assert(blockInts == 0);
+       blockInts = b;
+#endif
+
+       if (exceptionptr) {     
+               printf ("#### Initializer has thrown: ");
+               unicode_display (exceptionptr->vftbl->class->name);
+               printf ("\n");
+               fflush (stdout);
+               }
+
+       if (initverbose) {
+               sprintf (logtext, "Finished initializer for class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name);
+               dolog ();
+       }
+
+}
+
+
+
+
+/********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) ********/
+
+void class_showconstantpool (classinfo *c) 
+{
+       u4 i;
+       voidptr e;
+
+       printf ("---- dump of constant pool ----\n");
+
+       for (i=0; i<c->cpcount; i++) {
+               printf ("#%d:  ", (int) i);
+               
+               e = c -> cpinfos [i];
+               if (e) {
+                       
+                       switch (c -> cptags [i]) {
+                               case CONSTANT_Class:
+                                       printf ("Classreference -> ");
+                                       unicode_display ( ((classinfo*)e) -> name );
+                                       break;
+                               
+                               case CONSTANT_Fieldref:
+                                       printf ("Fieldref -> "); goto displayFMI;
+                               case CONSTANT_Methodref:
+                                       printf ("Methodref -> "); goto displayFMI;
+                               case CONSTANT_InterfaceMethodref:
+                                       printf ("InterfaceMethod -> "); goto displayFMI;
+                                 displayFMI:
+                                       {
+                                       constant_FMIref *fmi = e;
+                                       unicode_display ( fmi->class->name );
+                                       printf (".");
+                                       unicode_display ( fmi->name);
+                                       printf (" ");
+                                       unicode_display ( fmi->descriptor );
+                                   }
+                                       break;
+
+                               case CONSTANT_String:
+                                       printf ("String -> ");
+                                       unicode_display (e);
+                                       break;
+                               case CONSTANT_Integer:
+                                       printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+                                       break;
+                               case CONSTANT_Float:
+                                       printf ("Float -> %f", ((constant_float*)e) -> value);
+                                       break;
+                               case CONSTANT_Double:
+                                       printf ("Double -> %f", ((constant_double*)e) -> value);
+                                       break;
+                               case CONSTANT_Long:
+                                       {
+                                       u8 v = ((constant_long*)e) -> value;
+#if U8_AVAILABLE
+                                       printf ("Long -> %ld", (long int) v);
+#else
+                                       printf ("Long -> HI: %ld, LO: %ld\n", 
+                                           (long int) v.high, (long int) v.low);
+#endif 
+                                       }
+                                       break;
+                               case CONSTANT_NameAndType:
+                                       { constant_nameandtype *cnt = e;
+                                         printf ("NameAndType: ");
+                                         unicode_display (cnt->name);
+                                         printf (" ");
+                                         unicode_display (cnt->descriptor);
+                                       }
+                                       break;
+                               case CONSTANT_Utf8:
+                                       printf ("Utf8 -> ");
+                                       unicode_display (e);
+                                       break;
+                               case CONSTANT_Arraydescriptor:  {
+                                       printf ("Arraydescriptor: ");
+                                       displayarraydescriptor (e);
+                                       }
+                                       break;
+                               default: 
+                                       panic ("Invalid type of ConstantPool-Entry");
+                               }
+                               
+                       }
+
+               printf ("\n");
+               }
+       
+}
+
+
+
+/********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) ************/
+
+void class_showmethods (classinfo *c)
+{
+       u4 i;
+       
+       printf ("--------- Fields and Methods ----------------\n");
+       printf ("Flags: ");     printflags (c->flags);  printf ("\n");
+
+       printf ("This: "); unicode_display (c->name); printf ("\n");
+       if (c->super) {
+               printf ("Super: "); unicode_display (c->super->name); printf ("\n");
+               }
+       printf ("Index: %d\n", c->index);
+       
+       printf ("interfaces:\n");       
+       for (i=0; i < c-> interfacescount; i++) {
+               printf ("   ");
+               unicode_display (c -> interfaces[i] -> name);
+               printf (" (%d)\n", c->interfaces[i] -> index);
+               }
+
+       printf ("fields:\n");           
+       for (i=0; i < c -> fieldscount; i++) {
+               field_display (&(c -> fields[i]));
+               }
+
+       printf ("methods:\n");
+       for (i=0; i < c -> methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+               if ( !(m->flags & ACC_STATIC)) 
+                       printf ("vftblindex: %d   ", m->vftblindex);
+
+               method_display ( m );
+
+               }
+
+       printf ("Virtual function table:\n");
+       for (i=0; i<c->vftbl->vftbllength; i++) {
+               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
+               }
+
+}
+
+
+
+/*****************************************************************************/
+/******************* Funktionen fuer den Class-loader generell ***************/
+/*****************************************************************************/
+
+
+/********************* Funktion: loader_load **********************************
+
+       l"adt und linkt die ge"unschte Klasse und alle davon 
+       referenzierten Klassen und Interfaces
+       Return: Einen Zeiger auf diese Klasse
+
+******************************************************************************/
+
+classinfo *loader_load (unicode *topname)
+{
+       classinfo *top;
+       classinfo *c;
+       long int starttime=0,stoptime=0;
+       
+       intsDisable();                           /* schani */
+
+       if (getloadingtime) starttime = getcputime();
+       
+       
+       top = class_get (topname);
+
+       while ( (c = list_first(&unloadedclasses)) ) {
+               class_load (c);
+               }
+
+       while ( (c = list_first(&unlinkedclasses)) ) {
+               class_link (c);
+               }
+
+       
+       synchronize_caches ();
+       
+
+
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime-starttime);
+               }
+               
+       intsRestore();                      /* schani */
+
+       return top;
+}
+
+
+/******************* interne Funktion: loader_createarrayclass ****************
+
+       Erzeugt (und linkt) eine Klasse f"ur die Arrays.
+       
+******************************************************************************/
+
+static classinfo *loader_createarrayclass ()
+{
+       classinfo *c;
+       c = class_get ( unicode_new_char ("The_Array_Class") );
+       
+       list_remove (&unloadedclasses, c);
+       list_addlast (&unlinkedclasses, c);
+       c -> super = class_java_lang_Object;
+       
+       class_link (c);
+       return c;
+}
+
+
+
+/********************** Funktion: loader_init *********************************
+
+       Initialisiert alle Listen und l"adt alle Klassen, die vom System
+       und vom Compiler direkt ben"otigt werden.
+
+******************************************************************************/
+void loader_init ()
+{
+       interfaceindex = 0;
+       
+       list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
+       list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
+       list_init (&linkedclasses, OFFSET(classinfo, listnode) );
+
+
+       class_java_lang_Object = 
+               loader_load ( unicode_new_char ("java/lang/Object") );
+       class_java_lang_String = 
+               loader_load ( unicode_new_char ("java/lang/String") );
+       class_java_lang_ClassCastException = 
+               loader_load ( unicode_new_char ("java/lang/ClassCastException") );
+       class_java_lang_NullPointerException = 
+               loader_load ( unicode_new_char ("java/lang/NullPointerException") );
+       class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
+            unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
+       class_java_lang_NegativeArraySizeException = loader_load ( 
+            unicode_new_char ("java/lang/NegativeArraySizeException") );
+       class_java_lang_OutOfMemoryError = loader_load ( 
+            unicode_new_char ("java/lang/OutOfMemoryError") );
+       class_java_lang_ArrayStoreException =
+               loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
+       class_java_lang_ArithmeticException = 
+               loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
+       class_java_lang_ThreadDeath =                             /* schani */
+               loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
+
+       class_array = loader_createarrayclass ();
+
+
+       proto_java_lang_ClassCastException = 
+               builtin_new(class_java_lang_ClassCastException);
+       heap_addreference ( (void**) &proto_java_lang_ClassCastException);
+
+       proto_java_lang_NullPointerException = 
+               builtin_new(class_java_lang_NullPointerException);
+       heap_addreference ( (void**) &proto_java_lang_NullPointerException);
+
+       proto_java_lang_ArrayIndexOutOfBoundsException = 
+               builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
+       heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
+
+       proto_java_lang_NegativeArraySizeException = 
+               builtin_new(class_java_lang_NegativeArraySizeException);
+       heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
+
+       proto_java_lang_OutOfMemoryError = 
+               builtin_new(class_java_lang_OutOfMemoryError);
+       heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
+
+       proto_java_lang_ArithmeticException = 
+               builtin_new(class_java_lang_ArithmeticException);
+       heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
+
+       proto_java_lang_ArrayStoreException = 
+               builtin_new(class_java_lang_ArrayStoreException);
+       heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
+
+       proto_java_lang_ThreadDeath =                             /* schani */
+               builtin_new(class_java_lang_ThreadDeath);
+       heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
+}
+
+
+
+
+/********************* Funktion: loader_initclasses ****************************
+
+       initialisiert alle geladenen aber noch nicht initialisierten Klassen
+
+******************************************************************************/
+
+void loader_initclasses ()
+{
+       classinfo *c;
+       
+       intsDisable();                     /* schani */
+
+       if (makeinitializations) {
+               c = list_first (&linkedclasses);
+               while (c) {
+                       class_init (c);
+                       c = list_next (&linkedclasses, c);
+                       }
+               }
+
+       intsRestore();                      /* schani */
+}
+
+
+
+/******************** Funktion: loader_close **********************************
+
+       gibt alle Resourcen wieder frei
+       
+******************************************************************************/
+
+void loader_close ()
+{
+       classinfo *c;
+
+       while ( (c=list_first(&unloadedclasses)) ) {
+               list_remove (&unloadedclasses,c);
+               class_free (c);
+               }
+       while ( (c=list_first(&unlinkedclasses)) ) {
+               list_remove (&unlinkedclasses,c);
+               class_free (c);
+               }
+       while ( (c=list_first(&linkedclasses)) ) {
+               list_remove (&linkedclasses,c);
+               class_free (c);
+               }
+}
+
diff --git a/loader.h b/loader.h
new file mode 100644 (file)
index 0000000..190a645
--- /dev/null
+++ b/loader.h
@@ -0,0 +1,53 @@
+/******************************* loader.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the prototypes for the class loader.
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/14
+
+*******************************************************************************/
+
+
+/************************* program switches ***********************************/
+
+extern bool loadverbose;         /* Debug-Meldungen beim Laden ausgeben */
+extern bool linkverbose;
+extern bool initverbose;         /* Meldungen ausgeben, wenn Klasse 
+                                   initialisiert wird */
+extern bool makeinitializations; /* Klassen automatisch initialisieren */
+
+extern bool getloadingtime;
+extern long int loadingtime;     /* CPU-Zeit f"urs Laden der Klassen */
+
+extern list linkedclasses;       /* Liste aller fertig gelinkten Klassen */
+
+
+/************************ prototypes ******************************************/
+
+void loader_init ();
+void loader_close ();
+
+classinfo *loader_load (unicode *topname);
+void loader_initclasses ();
+
+classinfo *class_get (unicode *name);
+voidptr class_getconstant (classinfo *class, u4 pos, u4 ctype);
+u4 class_constanttype (classinfo *class, u4 pos);
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc);
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc);
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *dest);
+
+bool class_issubclass (classinfo *sub, classinfo *super);
+
+void class_init (classinfo *c);
+
+void class_showmethods (classinfo *c);
+void class_showconstantpool (classinfo *c);
+
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..d91cfc8
--- /dev/null
+++ b/main.c
@@ -0,0 +1,750 @@
+/******************************* main.c ****************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enthaelt die Funktion main() und die Variablen fuer die 
+       globalen Optionen.
+       Dieser Modul erledigt folgende Aufgaben:
+          - Bearbeiten der command-line-options
+          - Aufrufen aller Initialisierungsroutinen
+          - Aufrufen des Classloaders
+          - Starten der main - Methode
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Andi Krall          EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/29
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "compiler.h"
+#include "ncomp/ncomp.h"
+#include "loader.h"
+
+#include "asmpart.h"
+#include "builtin.h"
+#include "native.h"
+
+#include "threads/thread.h"            /* schani */
+
+bool compileall = false;
+int  newcompiler = true;               
+bool verbose =  false;
+
+#ifndef USE_THREADS
+void **stackbottom = 0;
+#endif
+
+
+/********************* interne Funktion: get_opt *****************************
+       
+       liest die n"achste Option aus der Kommandozeile
+       
+******************************************************************************/
+
+#define OPT_DONE  -1
+#define OPT_ERROR  0
+#define OPT_IGNORE 1
+
+#define OPT_CLASSPATH   2
+#define OPT_D           3  
+#define OPT_MS          4  
+#define OPT_MX          5  
+#define OPT_VERBOSE1    6  
+#define OPT_VERBOSE     7  
+#define OPT_VERBOSEGC   8         
+#define OPT_VERBOSECALL 9          
+#define OPT_IEEE        10
+#define OPT_SOFTNULL    11
+#define OPT_TIME        12
+#define OPT_STAT        13
+#define OPT_LOG         14  
+#define OPT_CHECK       15
+#define OPT_LOAD        16  
+#define OPT_METHOD      17  
+#define OPT_SIGNATURE   18  
+#define OPT_SHOW        19 
+#define OPT_ALL         20 
+#define OPT_OLD         21 
+
+struct { char *name; bool arg; int value; } opts[] = {
+  { "classpath",   true,   OPT_CLASSPATH },
+  { "D",           true,   OPT_D },
+  { "ms",          true,   OPT_MS },
+  { "mx",          true,   OPT_MX },
+  { "noasyncgc",   false,  OPT_IGNORE },  
+  { "noverify",    false,  OPT_IGNORE },  
+  { "oss",         true,   OPT_IGNORE },  
+  { "ss",          true,   OPT_IGNORE },  
+  { "v",           false,  OPT_VERBOSE1 },
+  { "verbose",     false,  OPT_VERBOSE },
+  { "verbosegc",   false,  OPT_VERBOSEGC },
+  { "verbosecall", false,  OPT_VERBOSECALL },
+  { "ieee",        false,  OPT_IEEE },
+  { "softnull",    false,  OPT_SOFTNULL },
+  { "time",        false,  OPT_TIME },
+  { "stat",        false,  OPT_STAT },
+  { "log",         true,   OPT_LOG },
+  { "c",           true,   OPT_CHECK },
+  { "l",           false,  OPT_LOAD },
+  { "m",           true,   OPT_METHOD },
+  { "sig",         true,   OPT_SIGNATURE },
+  { "s",           true,   OPT_SHOW },          
+  { "all",         false,  OPT_ALL },          
+  { "old",         false,  OPT_OLD },          
+  { NULL,  false, 0 }
+};
+
+static int opt_ind = 1;
+static char *opt_arg;
+
+static int get_opt (int argc, char **argv) 
+{
+       char *a;
+       int i;
+       
+       if (opt_ind >= argc) return OPT_DONE;
+       
+       a = argv[opt_ind];
+       if (a[0] != '-') return OPT_DONE;
+
+       for (i=0; opts[i].name; i++) {
+               if (! opts[i].arg) {
+                       if (strcmp(a+1, opts[i].name) == 0) {  /* boolean option found */
+                               opt_ind++;
+                               return opts[i].value;
+                               }
+                       }
+               else {
+                       if (strcmp(a+1, opts[i].name) == 0) { /* parameter option found */
+                               opt_ind++;
+                               if (opt_ind < argc) {
+                                       opt_arg = argv[opt_ind];
+                                       opt_ind++;
+                                       return opts[i].value;
+                                       }
+                               return OPT_ERROR;
+                               }
+                       else {
+                               size_t l = strlen(opts[i].name);
+                               if (strlen(a+1) > l) {
+                                       if (memcmp (a+1, opts[i].name, l)==0) {
+                                               opt_ind++;
+                                               opt_arg = a+1+l;
+                                               return opts[i].value;
+                                               }
+                                       }
+                               }
+                       }
+               } /* end for */ 
+
+       return OPT_ERROR;
+}
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JavaVM-Compilers auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+       printf ("USAGE: cacao [options] classname [program arguments\n");
+       printf ("Options:\n");
+       printf ("          -classpath path ...... specify a path to look for classes\n");
+       printf ("          -Dpropertyname=value . add an entry to the property list\n");
+       printf ("          -mx maxmem[k|m] ...... specify the size for the heap\n");
+       printf ("          -ms initmem[k|m] ..... specify the initial size for the heap\n");
+       printf ("          -v ................... write state-information\n");
+       printf ("          -verbose ............. write more information\n");
+       printf ("          -verbosegc ........... write message for each GC\n");
+       printf ("          -verbosecall ......... write message for each call\n");
+       printf ("          -ieee ................ use ieee compliant arithmetic\n");
+       printf ("          -softnull ............ use software nullpointer check\n");
+       printf ("          -time ................ measure the runtime\n");
+       printf ("          -stat ................ detailed compiler statistics\n");
+       printf ("          -log logfile ......... specify a name for the logfile\n");
+       printf ("          -c(heck) b(ounds...... don't check array bounds\n");
+       printf ("                   s(ync) ...... don't check for synchronization\n");
+       printf ("          -l ................... don't start the class after loading\n");
+       printf ("          -all ................. compile all methods, no execution\n");
+       printf ("          -old ................. use old JIT compiler\n");
+       printf ("          -m ................... compile only a specific method\n");
+       printf ("          -sig ................. specify signature for a specific method\n");
+       printf ("          -s(how)m(ethods) ..... show all methods&fields of a class\n");
+       printf ("                 c(onstants) ... show the constant pool\n");
+       printf ("                 a(ssembler) ... show disassembled listing\n");
+       printf ("                 s(tack) ....... show stack for every javaVM-command\n");
+       printf ("                 i(ntermediate). show intermediate representation\n");
+       printf ("                 u(nicode) ..... show the unicode - hash\n");
+}   
+
+
+
+/***************************** Funktion: print_times *********************
+
+       gibt eine Aufstellung der verwendeten CPU-Zeit aus
+
+**************************************************************************/
+
+static void print_times()
+{
+       long int totaltime = getcputime();
+       long int runtime = totaltime - loadingtime - compilingtime;
+
+       sprintf (logtext, "Time for loading classes: %ld secs, %ld millis",
+            loadingtime / 1000000, (loadingtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Time for compiling code:  %ld secs, %ld millis",
+            compilingtime / 1000000, (compilingtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Time for running program: %ld secs, %ld millis",
+            runtime / 1000000, (runtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Total time: %ld secs, %ld millis",
+            totaltime / 1000000, (totaltime % 1000000) / 1000);
+       dolog();
+}
+
+
+
+
+
+
+/***************************** Funktion: print_stats *********************
+
+       outputs detailed compiler statistics
+
+**************************************************************************/
+
+static void print_stats()
+{
+       sprintf (logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
+       dolog();
+       sprintf (logtext, "Number of compiled Methods: %d", count_methods);
+       dolog();
+       sprintf (logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
+       dolog();
+       sprintf (logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
+       dolog();
+       sprintf (logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
+       dolog();
+       sprintf (logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
+       dolog();
+       sprintf (logtext, "Size of compiled JavaVM-Instructions:   %d(%d)", count_javacodesize,
+                                                     count_javacodesize - count_methods * 18);
+       dolog();
+       sprintf (logtext, "Size of compiled Exception Tables:      %d", count_javaexcsize);
+       dolog();
+       sprintf (logtext, "Value of extended instruction set var:  %d", has_ext_instr_set);
+       dolog();
+       sprintf (logtext, "Number of Alpha-Instructions: %d", count_code_len >> 2);
+       dolog();
+       sprintf (logtext, "Number of Spills: %d", count_spills);
+       dolog();
+       sprintf (logtext, "Number of Activ    Pseudocommands: %5d", count_pcmd_activ);
+       dolog();
+       sprintf (logtext, "Number of Drop     Pseudocommands: %5d", count_pcmd_drop);
+       dolog();
+       sprintf (logtext, "Number of Const    Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
+       dolog();
+       sprintf (logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+       dolog();
+       sprintf (logtext, "Number of Move     Pseudocommands: %5d", count_pcmd_move);
+       dolog();
+       sprintf (logtext, "Number of Load     Pseudocommands: %5d", count_load_instruction);
+       dolog();
+       sprintf (logtext, "Number of Store    Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+       dolog();
+       sprintf (logtext, "Number of OP       Pseudocommands: %5d", count_pcmd_op);
+       dolog();
+       sprintf (logtext, "Number of DUP      Pseudocommands: %5d", count_dup_instruction);
+       dolog();
+       sprintf (logtext, "Number of Mem      Pseudocommands: %5d", count_pcmd_mem);
+       dolog();
+       sprintf (logtext, "Number of Method   Pseudocommands: %5d", count_pcmd_met);
+       dolog();
+       sprintf (logtext, "Number of Branch   Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
+                         count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+       dolog();
+       sprintf (logtext, "Number of Table    Pseudocommands: %5d", count_pcmd_table);
+       dolog();
+       sprintf (logtext, "Number of Useful   Pseudocommands: %5d", count_pcmd_table +
+                count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+       dolog();
+       sprintf (logtext, "Number of Null Pointer Checks:     %5d", count_check_null);
+       dolog();
+       sprintf (logtext, "Number of Array Bound Checks:      %5d", count_check_bound);
+       dolog();
+       sprintf (logtext, "Number of Try-Blocks: %d", count_tryblocks);
+       dolog();
+       sprintf (logtext, "Maximal count of stack elements:   %d", count_max_new_stack);
+       dolog();
+       sprintf (logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+       dolog();
+       sprintf (logtext, "Distribution of stack sizes at block boundary");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
+               count_block_stack[1],count_block_stack[2],count_block_stack[3],count_block_stack[4],
+               count_block_stack[5],count_block_stack[6],count_block_stack[7],count_block_stack[8],
+               count_block_stack[9],count_block_stack[10]);
+       dolog();
+       sprintf (logtext, "Distribution of store stack depth");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
+               count_store_depth[1],count_store_depth[2],count_store_depth[3],count_store_depth[4],
+               count_store_depth[5],count_store_depth[6],count_store_depth[7],count_store_depth[8],
+               count_store_depth[9],count_store_depth[10]);
+       dolog();
+       sprintf (logtext, "Distribution of store creator chains first part");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9  ");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
+               count_store_length[1],count_store_length[2],count_store_length[3],count_store_length[4],
+               count_store_length[5],count_store_length[6],count_store_length[7],count_store_length[8],
+               count_store_length[9]);
+       dolog();
+       sprintf (logtext, "Distribution of store creator chains second part");
+       dolog();
+       sprintf (logtext, "   10   11   12   13   14   15   16   17   18   19  >=20");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
+               count_store_length[11],count_store_length[12],count_store_length[13],count_store_length[14],
+               count_store_length[15],count_store_length[16],count_store_length[17],count_store_length[18],
+               count_store_length[19],count_store_length[20]);
+       dolog();
+       sprintf (logtext, "Distribution of analysis iterations");
+       dolog();
+       sprintf (logtext, "    1    2    3    4    >=5");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0],count_analyse_iterations[1],
+               count_analyse_iterations[2],count_analyse_iterations[3],count_analyse_iterations[4]);
+       dolog();
+       sprintf (logtext, "Distribution of basic blocks per method");
+       dolog();
+       sprintf (logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75  >75");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
+               count_method_bb_distribution[1],count_method_bb_distribution[2],count_method_bb_distribution[3],
+               count_method_bb_distribution[4],count_method_bb_distribution[5],count_method_bb_distribution[6],
+               count_method_bb_distribution[7],count_method_bb_distribution[8]);
+       dolog();
+       sprintf (logtext, "Distribution of basic block sizes");
+       dolog();
+       sprintf (logtext,
+       "  1    2    3    4   5   6   7   8   9  10 <13 <15 <17 <19 <21 <26 <31 >30");
+       dolog();
+       sprintf (logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
+               count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
+               count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
+               count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
+               count_block_size_distribution[9], count_block_size_distribution[10],count_block_size_distribution[11],
+               count_block_size_distribution[12],count_block_size_distribution[13],count_block_size_distribution[14],
+               count_block_size_distribution[15],count_block_size_distribution[16],count_block_size_distribution[17]);
+       dolog();
+       sprintf (logtext, "Size of Code Area (Kb):  %10.3f", (float) count_code_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of data Area (Kb):  %10.3f", (float) count_data_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
+       dolog();
+       sprintf (logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_unicode_len) / 1024);
+       dolog();
+       sprintf (logtext, "Size of Vftbl (Kb):      %10.3f", (float) count_vftbl_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of comp stub (Kb):  %10.3f", (float) count_cstub_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of Unicode (Kb):    %10.3f", (float) count_unicode_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of VMCode (Kb):     %10.3f(%d)", (float) count_vmcode_len / 1024,
+                                                     count_vmcode_len - 18 * count_all_methods);
+       dolog();
+       sprintf (logtext, "Size of ExTable (Kb):    %10.3f", (float) count_extable_len / 1024);
+       dolog();
+       sprintf (logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
+       dolog();
+}
+
+
+/********** Funktion: class_compile_methods   (nur f"ur Debug-Zwecke) ********/
+
+void class_compile_methods ()
+{
+       int        i;
+       classinfo  *c;
+       methodinfo *m;
+       
+       c = list_first (&linkedclasses);
+       while (c) {
+               for (i = 0; i < c -> methodscount; i++) {
+                       m = &(c->methods[i]);
+                       if (m->jcode) {
+                               if (newcompiler)
+                                       (void) new_compile(m);
+                               else
+                                       (void) compiler_compile(m);
+                               }
+                       }
+               c = list_next (&linkedclasses, c);
+               }
+}
+
+
+/************************** Funktion: main *******************************
+
+   Das Hauptprogramm.
+   Wird vom System zu Programstart aufgerufen (eh klar).
+   
+**************************************************************************/
+
+
+int main(int argc, char **argv)
+{
+       s4 i,j;
+       char *cp;
+       classinfo *topclass;
+       java_objectheader *exceptionptr;
+       void *dummy;
+       
+
+   /********** interne (nur fuer main relevante Optionen) **************/
+   
+       char logfilename[200] = "";
+       u4 heapsize = 16000000;
+       u4 heapstartsize = 200000;
+       char classpath[500] = ".:/usr/local/lib/java/classes";
+       bool showmethods = false;
+       bool showconstantpool = false;
+       bool showunicode = false;
+       bool startit = true;
+       char *specificmethodname = NULL;
+       char *specificsignature = NULL;
+
+#ifndef USE_THREADS
+       stackbottom = &dummy;
+#endif
+
+
+   /************ Infos aus der Environment lesen ************************/
+
+       cp = getenv ("CLASSPATH");
+       if (cp) {
+               strcpy (classpath, cp);
+               }
+
+   /***************** Interpretieren der Kommandozeile *****************/
+   
+   checknull = false;
+   checkfloats = false;
+
+       while ( (i = get_opt(argc,argv)) != OPT_DONE) {
+
+               switch (i) {
+                       case OPT_IGNORE: break;
+                       
+                       case OPT_CLASSPATH:    
+                               strcpy (classpath + strlen(classpath), ":");
+                               strcpy (classpath + strlen(classpath), opt_arg);
+                               break;
+                               
+                       case OPT_D:
+                               {
+                               int n,l=strlen(opt_arg);
+                               for (n=0; n<l; n++) {
+                                       if (opt_arg[n]=='=') {
+                                               opt_arg[n] = '\0';
+                                               attach_property (opt_arg, opt_arg+n+1);
+                                               goto didit;
+                                               }
+                                       }
+                               print_usage();
+                               exit(10);
+                                       
+                               didit: ;
+                               }       
+                               break;
+                               
+                       case OPT_MS:
+                       case OPT_MX:
+                               if (opt_arg[strlen(opt_arg)-1] == 'k') {
+                                       j = 1024 * atoi(opt_arg);
+                                       }
+                               else if (opt_arg[strlen(opt_arg)-1] == 'm') {
+                                       j = 1024 * 1024 * atoi(opt_arg);
+                                       }
+                               else j = atoi(opt_arg);
+                               
+                               if (i==OPT_MX) heapsize = j;
+                               else heapstartsize = j;
+                               break;
+
+                       case OPT_VERBOSE1:
+                               verbose = true;
+                               break;
+                                                               
+                       case OPT_VERBOSE:
+                               verbose = true;
+                               loadverbose = true;
+                               initverbose = true;
+                               compileverbose = true;
+                               break;
+                               
+                       case OPT_VERBOSEGC:
+                               collectverbose = true;
+                               break;
+                               
+                       case OPT_VERBOSECALL:
+                               runverbose = true;
+                               break;
+                               
+                       case OPT_IEEE:
+                               checkfloats = true;
+                               break;
+
+                       case OPT_SOFTNULL:
+                               checknull = true;
+                               break;
+
+                       case OPT_TIME:
+                               getcompilingtime = true;
+                               getloadingtime = true;
+                               break;
+                                       
+                       case OPT_STAT:
+                               statistics = true;
+                               break;
+                                       
+                       case OPT_LOG:
+                               strcpy (logfilename, opt_arg);
+                               break;
+                       
+                       
+                       case OPT_CHECK:
+                       for (j=0; j<strlen(opt_arg); j++) {
+                               switch (opt_arg[j]) {
+                               case 'b': checkbounds=false; break;
+                                       case 's': checksync=false; break;
+                               default:  print_usage();
+                                         exit(10);
+                               }
+                               }
+                       break;
+                       
+                       case OPT_LOAD:
+                               startit = false;
+                               makeinitializations = false;
+                               break;
+
+                       case OPT_METHOD:
+                               startit = false;
+                               specificmethodname = opt_arg;                   
+                               makeinitializations = false;
+                       break;
+                       
+                       case OPT_SIGNATURE:
+                               specificsignature = opt_arg;                    
+                       break;
+                       
+                       case OPT_ALL:
+                               compileall = true;              
+                               startit = false;
+                               makeinitializations = false;
+                       break;
+                       
+                       case OPT_OLD:
+                               newcompiler = false;                    
+                               checknull = true;
+                       break;
+                       
+               case OPT_SHOW:       /* Anzeigeoptionen */
+                       for (j=0; j<strlen(opt_arg); j++) {             
+                               switch (opt_arg[j]) {
+                               case 'm':  showmethods=true; break;
+                               case 'c':  showconstantpool=true; break;
+                               case 'a':  showdisassemble=true; compileverbose=true; break;
+                               case 's':  showstack=true; compileverbose=true; break;
+                               case 'i':  showintermediate=true; compileverbose=true; break;
+                               case 'u':  showunicode=true; break;
+                               default:   print_usage();
+                                      exit(10);
+                               }
+                               }
+                       break;
+                       
+                       default:
+                               print_usage();
+                               exit(10);
+                       }
+                       
+                       
+               }
+   
+   
+       if (opt_ind >= argc) {
+               print_usage ();
+               exit(10);
+               }
+
+
+   /**************************** Programmstart *****************************/
+
+       log_init (logfilename);
+       if (verbose) {
+               log_text (
+               "CACAO started -------------------------------------------------------");
+               }
+       
+       suck_init (classpath);
+       native_setclasspath (classpath);
+               
+       unicode_init();
+       heap_init(heapsize, heapstartsize, &dummy);
+       loader_init();
+       compiler_init();
+       ncomp_init();
+
+       native_loadclasses ();
+
+
+   /*********************** JAVA-Klassen laden  ***************************/
+   
+       cp = argv[opt_ind++];
+       for (i=strlen(cp)-1; i>=0; i--) {     /* Punkte im Klassennamen */
+               if (cp[i]=='.') cp[i]='/';        /* auf slashes umbauen */
+               }
+
+       topclass = loader_load ( unicode_new_char (cp) );
+
+       gc_init();
+
+#ifdef USE_THREADS
+       initThreads((u1*)&dummy);                   /* schani */
+#endif
+
+   /************************* Arbeitsroutinen starten ********************/
+
+       if (startit) {
+               methodinfo *mainmethod;
+               java_objectarray *a; 
+
+               mainmethod = class_findmethod (
+                               topclass,
+                               unicode_new_char ("main"), 
+                               unicode_new_char ("([Ljava/lang/String;)V")
+                               );
+               if (!mainmethod) panic ("Can not find method 'void main(String[])'");
+               if ((mainmethod->flags & ACC_STATIC) != ACC_STATIC) panic ("main is not static!");
+                       
+               a = builtin_anewarray (argc - opt_ind, class_java_lang_String);
+               for (i=opt_ind; i<argc; i++) {
+                       a->data[i-opt_ind] = javastring_new (unicode_new_char (argv[i]) );
+                       }
+               exceptionptr = asm_calljavamethod (mainmethod, a, NULL,NULL,NULL );
+       
+               if (exceptionptr) {
+                       printf ("#### Program has thrown: ");
+                       unicode_display (exceptionptr->vftbl->class->name);
+                       printf ("\n");
+                       }
+
+/*             killThread(currentThread); */
+
+               }
+
+       /************* Auf Wunsch alle Methode "ubersetzen ********************/
+
+       if (compileall) {
+               class_compile_methods();
+               }
+
+
+       /******** Auf Wunsch eine spezielle Methode "ubersetzen ***************/
+
+       if (specificmethodname) {
+               methodinfo *m;
+               if (specificsignature)
+                       m = class_findmethod(topclass, 
+                                       unicode_new_char(specificmethodname),
+                                       unicode_new_char(specificsignature));
+               else
+                       m = class_findmethod(topclass, 
+                                       unicode_new_char(specificmethodname), NULL);
+               if (!m) panic ("Specific method not found");
+               if (newcompiler)
+                       (void) new_compile(m);
+               else
+                       (void) compiler_compile(m);
+               }
+
+       /********************* Debug-Tabellen ausgeben ************************/
+                               
+       if (showmethods) class_showmethods (topclass);
+       if (showconstantpool)  class_showconstantpool (topclass);
+       if (showunicode)       unicode_show ();
+
+   
+
+   /************************ Freigeben aller Resourcen *******************/
+
+       compiler_close ();
+       loader_close ();
+       heap_close ();
+       unicode_close ( literalstring_free );
+
+
+   /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+       if (verbose || getcompilingtime || statistics) {
+               log_text ("CACAO terminated");
+               if (statistics)
+                       print_stats ();
+               if (getcompilingtime)
+                       print_times ();
+               mem_usagelog(1);
+               }
+               
+       exit(0);
+       return 1;
+}
+
+
+
+/************************************ SHUTDOWN-Funktion *********************************
+
+       Terminiert das System augenblicklich, ohne den Speicher
+       explizit freizugeben (eigentlich nur f"ur abnorme 
+       Programmterminierung)
+       
+*****************************************************************************************/
+
+void cacao_shutdown(s4 status)
+{
+       if (verbose || getcompilingtime || statistics) {
+               log_text ("CACAO terminated by shutdown");
+               if (statistics)
+                       print_stats ();
+               if (getcompilingtime)
+                       print_times ();
+               mem_usagelog(0);
+               sprintf (logtext, "Exit status: %d\n", (int) status);
+               dolog();
+               }
+               
+       exit(status);
+}
diff --git a/nat/io.c b/nat/io.c
new file mode 100644 (file)
index 0000000..c7abc6b
--- /dev/null
+++ b/nat/io.c
@@ -0,0 +1,473 @@
+/****************************** nat/io.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the native functions for class java.io.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/22
+
+*******************************************************************************/
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/types.h>
+#ifdef _OSF_SOURCE 
+#include <sys/mode.h>
+#endif
+#include <sys/stat.h>
+
+#include "../threads/threadio.h"                    /* schani */
+
+/*
+ * io is performed through the threaded... functions, since io operations may
+ * block and the corresponding thread must, in this case, be suspended.
+ *
+ * schani
+ */
+
+/********************* java.io.FileDescriptor ********************************/
+
+s4 java_io_FileDescriptor_valid (struct java_io_FileDescriptor* this)
+{
+       if (this->fd >= 0) return 1;
+       return 0;
+}
+
+struct java_io_FileDescriptor* java_io_FileDescriptor_initSystemFD 
+        (struct java_io_FileDescriptor* fd, s4 handle)
+{
+       switch (handle) {
+       case 0:  fd -> fd = fileno(stdin); 
+                break;
+       case 1:  fd -> fd = fileno(stdout);
+                break;
+       case 2:  fd -> fd = fileno(stderr);
+                break;
+       default: panic ("Invalid file descriptor number");
+       }
+
+       threadedFileDescriptor(fd->fd);
+
+       return fd;
+}
+
+
+/************************* java.io.FileInputStream ***************************/
+
+
+void java_io_FileInputStream_open 
+       (struct java_io_FileInputStream* this, struct java_lang_String* name)
+{
+       s4 fd;
+       char *fname = javastring_tochar ((java_objectheader*)name);
+
+       if (!fname) goto fail;
+
+       fd = open (fname, O_RDONLY, 0);
+       if (fd<0) goto fail;
+       
+       threadedFileDescriptor(fd);
+
+       this->fd->fd = fd;
+       return;
+
+       fail:
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               return;
+}
+
+s4 java_io_FileInputStream_read (struct java_io_FileInputStream* this)
+{
+       s4 r;
+       u1 buffer[1];
+       r = threadedRead (this->fd->fd, (char *) buffer, 1);    
+
+       if (r>0) return buffer[0];
+       if (r==0) return -1;
+       
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return 0;
+}
+
+
+s4 java_io_FileInputStream_readBytes (struct java_io_FileInputStream* this, 
+     java_bytearray* buffer, s4 start, s4 len)
+{
+       s4 ret = threadedRead (this->fd->fd, (char *) buffer->data+start, len);
+       if (ret>0) return ret;
+       if (ret==0) return -1;
+       
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return 0;
+}
+
+
+s8 java_io_FileInputStream_skip 
+       (struct java_io_FileInputStream* this, s8 numbytes)
+{
+       s4 ret = lseek (this->fd->fd, builtin_l2i(numbytes), SEEK_CUR);
+       if (ret>0) return builtin_i2l(ret);
+       if (ret==0) return builtin_i2l(-1);
+       
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return builtin_i2l(0);
+}
+
+s4 java_io_FileInputStream_available (struct java_io_FileInputStream* this)
+{
+       struct stat buffer;
+       s4 r1,r2;
+       
+       r1 = fstat (this->fd->fd, &buffer);
+       r2 = lseek(this->fd->fd, 0, SEEK_CUR);
+       
+       if ( (r1 >= 0) && (r2 >= 0) )  
+               return buffer.st_size - r2; 
+
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return 0;
+}
+
+void java_io_FileInputStream_close (struct java_io_FileInputStream* this)
+{
+       if (this->fd->fd >= 0) {
+               s4 r = close (this->fd->fd);
+               this->fd->fd = -1;
+               if (r < 0) 
+                       exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+
+
+
+
+
+/*************************** java.io.FileOutputStream ************************/
+
+
+void java_io_FileOutputStream_open (struct java_io_FileOutputStream* this, 
+                                  struct java_lang_String* name)
+{
+       s4 fd;
+       char *fname = javastring_tochar ((java_objectheader*)name);
+       if (!fname) goto fail;
+       
+       fd = creat (fname, 0666);
+       if (fd<0) goto fail;
+       
+       threadedFileDescriptor(fd);
+
+       this->fd->fd = fd;
+       return;
+
+       fail:
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               return;
+}
+
+                                
+void java_io_FileOutputStream_write
+          (struct java_io_FileOutputStream* this, s4 byte)
+{
+       u1 buffer[1];
+       s4 l;
+
+       buffer[0] = byte;
+       l = threadedWrite (this->fd->fd, (char *) buffer, 1);
+
+       if (l<1) {
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+       
+void java_io_FileOutputStream_writeBytes (struct java_io_FileOutputStream* this,
+                            java_bytearray* buffer, s4 start, s4 len)
+{
+       s4 o;
+
+       if (len == 0)
+               return;
+       o = threadedWrite (this->fd->fd, (char *) buffer->data+start, len);
+       if (o!=len) 
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+}
+                            
+void java_io_FileOutputStream_close (struct java_io_FileOutputStream* this)
+{
+       if (this->fd->fd >= 0) {
+               s4 r = close (this->fd->fd);
+               this->fd->fd = -1;
+               if (r<0) 
+                       exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+
+
+
+/************************** java.io.File **************************************/
+
+s4 java_io_File_exists0 (struct java_io_File* this)
+{
+       struct stat buffer;
+       char *path;
+       int err;
+       
+       path = javastring_tochar( (java_objectheader*) (this->path));
+       
+       err = stat (path, &buffer);
+       if (err==0) return 1;
+       return 0;
+}      
+
+s4 java_io_File_canWrite0 (struct java_io_File* this) 
+{
+       int err;
+       err = access (javastring_tochar( (java_objectheader*) (this->path)), W_OK);
+       if (err==0) return 1;
+       return 0;
+}
+
+s4 java_io_File_canRead0 (struct java_io_File* this)
+{
+       int err;
+       err = access (javastring_tochar( (java_objectheader*) (this->path)), R_OK);
+       if (err==0) return 1;
+       return 0;
+}
+
+s4 java_io_File_isFile0 (struct java_io_File* this)
+{
+       struct stat buffer;
+       char *path;
+       int err;
+       
+       path = javastring_tochar( (java_objectheader*) (this->path));
+       
+       err = stat (path, &buffer);
+       if (err!=0) return 0;
+       if (S_ISREG(buffer.st_mode)) return 1;
+       return 0;
+}
+
+s4 java_io_File_isDirectory0 (struct java_io_File* this)
+{
+       struct stat buffer;
+       char *path;
+       int err;
+       
+       path = javastring_tochar( (java_objectheader*) (this->path));
+       
+       err = stat (path, &buffer);
+       if (err!=0) return 0;
+       if (S_ISDIR(buffer.st_mode)) return 1;
+       return 0;
+}
+s8 java_io_File_lastModified0 (struct java_io_File* this) 
+{
+       struct stat buffer;
+       int err;
+       err = stat (javastring_tochar( (java_objectheader*) (this->path)),  &buffer);
+       if (err!=0) return builtin_i2l(0);
+       return builtin_lmul (builtin_i2l(buffer.st_mtime), builtin_i2l(1000) );
+}
+
+s8 java_io_File_length0 (struct java_io_File* this)
+{
+       struct stat buffer;
+       int err;
+       err = stat (javastring_tochar( (java_objectheader*) (this->path)),  &buffer);
+       if (err!=0) return builtin_i2l(0);
+       return builtin_i2l(buffer.st_size);
+}
+
+s4 java_io_File_mkdir0 (struct java_io_File* this) 
+{ 
+       char *name = javastring_tochar ( (java_objectheader*) (this->path) );
+       int err = mkdir (name, 0777);
+       if (err==0) return 1;
+       return 0;
+}
+
+s4 java_io_File_renameTo0 (struct java_io_File* this, struct java_io_File* new) 
+{ 
+#define MAXPATHLEN 200
+       char newname[MAXPATHLEN];
+       char *n = javastring_tochar ( (java_objectheader*) (new->path) );
+       int err;
+       
+       if (strlen(n)>=MAXPATHLEN) return 0;
+       strcpy (newname, n);
+       n = javastring_tochar ( (java_objectheader*) (this->path) );
+       err = rename (n, newname);
+       if (err==0) return 1;
+       return 0;
+}
+
+s4 java_io_File_delete0 (struct java_io_File* this) 
+{ 
+       int err;
+       err = remove (javastring_tochar ( (java_objectheader*) (this->path) ) );
+       if (err==0) return 1;
+       return 0; 
+}
+
+java_objectarray* java_io_File_list0 (struct java_io_File* this) 
+{ 
+       char *name;
+       DIR *d;
+       int i,len, namlen;
+       java_objectarray *a;
+       struct dirent *ent;
+       struct java_lang_String *n;
+       char entbuffer[257];
+       
+       name = javastring_tochar ( (java_objectheader*) (this->path) );
+       d = opendir(name);
+       if (!d) return NULL;
+       
+       len=0;
+       while (readdir(d) != NULL) len++;
+       rewinddir (d);
+       
+       a = builtin_anewarray (len, class_java_lang_String);
+       if (!a) {
+               closedir(d);
+               return NULL;
+               }
+               
+       for (i=0; i<len; i++) {
+               if ( (ent = readdir(d)) != NULL) {
+                       namlen = strlen(ent->d_name);
+                       memcpy (entbuffer, ent->d_name, namlen);
+                       entbuffer[namlen] = '\0';
+                       
+                       n = (struct java_lang_String*) 
+                               javastring_new_char (entbuffer);
+                       
+                       a -> data[i] = (java_objectheader*) n;
+                       }
+               }
+
+
+       closedir(d);
+       return a;
+}
+
+s4 java_io_File_isAbsolute (struct java_io_File* this) 
+{ 
+       char *name = javastring_tochar ( (java_objectheader*) (this->path) );
+       if (name[0] == '/') return 1;
+       return 0;
+}
+
+
+
+
+/********************** java.io.RandomAccessFile *****************************/
+
+void java_io_RandomAccessFile_open (struct java_io_RandomAccessFile* this, 
+               struct java_lang_String* name, s4 writeable)
+{
+       s4 fd;
+       char *fname = javastring_tochar ((java_objectheader*)name);
+       
+       if (writeable) fd = open (fname, O_RDWR, 0);
+       else           fd = open (fname, O_RDONLY, 0);
+       if (fd==-1) goto fail;
+
+       threadedFileDescriptor(fd);
+       
+       this->fd->fd = fd;
+       return;
+
+       fail:
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               return;
+}
+
+s4 java_io_RandomAccessFile_read (struct java_io_RandomAccessFile* this)
+{ 
+       s4 r;
+       u1 buffer[1];
+       r = threadedRead (this->fd->fd, (char *) buffer, 1);    
+       if (r>0) return buffer[1];
+       if (r==0) return -1;
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return 0;
+}
+
+s4 java_io_RandomAccessFile_readBytes (struct java_io_RandomAccessFile* this, 
+     java_bytearray* buffer, s4 start, s4 len)
+{
+       s4 r = threadedRead (this->fd->fd, (char *) buffer->data+start, len);
+       if (r>0) return r;
+       if (r==0) return -1;
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return 0;
+}
+
+void java_io_RandomAccessFile_write 
+       (struct java_io_RandomAccessFile* this, s4 byte)
+{ 
+       u1 buffer[1];
+       int r;
+       buffer[1] = byte;
+       r = write (this->fd->fd, buffer, 1);
+       if (r<0) {
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+
+void java_io_RandomAccessFile_writeBytes (struct java_io_RandomAccessFile* this, 
+                            java_bytearray* buffer, s4 start, s4 len)
+{
+       s4 o;
+       if (len == 0)
+               return;
+       o = threadedWrite (this->fd->fd, (char *) buffer->data+start, len);
+       if (o!=len) exceptionptr = native_new_and_init (class_java_io_IOException);
+}
+               
+s8 java_io_RandomAccessFile_getFilePointer 
+        (struct java_io_RandomAccessFile* this)
+{
+       s4 p = lseek (this->fd->fd, 0, SEEK_CUR);
+       if (p>=0) return builtin_i2l(p);
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return builtin_i2l(0);
+}
+
+void java_io_RandomAccessFile_seek 
+           (struct java_io_RandomAccessFile* this, s8 offset)
+{
+       s4 p = lseek (this->fd->fd, builtin_l2i(offset), SEEK_SET); 
+       if (p<0) {
+               exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+
+s8 java_io_RandomAccessFile_length (struct java_io_RandomAccessFile* this)
+{
+       struct stat buffer;
+       s4 r = fstat(this->fd->fd, &buffer);
+       if (r>=0) return builtin_i2l(buffer.st_size);
+       exceptionptr = native_new_and_init (class_java_io_IOException);
+       return builtin_i2l(0);
+}
+
+void java_io_RandomAccessFile_close (struct java_io_RandomAccessFile* this)
+{      
+       if (this->fd->fd >= 0) {
+               s4 r = close (this->fd->fd);
+               this->fd->fd = -1;
+               if (r<0) 
+                       exceptionptr = native_new_and_init (class_java_io_IOException);
+               }
+}
+
diff --git a/nat/lang.c b/nat/lang.c
new file mode 100644 (file)
index 0000000..4561319
--- /dev/null
@@ -0,0 +1,918 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** nat/lang.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the native functions for class java.lang.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/06/10
+
+*******************************************************************************/
+
+#include <math.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#include "../threads/thread.h"                       /* schani */
+#include "../threads/locks.h"
+
+static void use_class_as_object (classinfo *c) 
+{
+       c->header.vftbl = class_java_lang_Class -> vftbl;
+}
+
+
+/************************************** java.lang.Object ***********************************/
+
+struct java_lang_Class* java_lang_Object_getClass (struct java_lang_Object* this)
+{
+       classinfo *c = this->header.vftbl -> class;
+       use_class_as_object (c);
+       return (java_lang_Class*) c;
+}
+
+s4 java_lang_Object_hashCode (struct java_lang_Object* this)
+{
+       return ((char*) this) - ((char*) 0);    
+}
+
+
+struct java_lang_Object* java_lang_Object_clone (struct java_lang_Object* this)
+{
+       classinfo *c;
+       java_lang_Object *new;
+
+       if (((java_objectheader*)this)->vftbl->class == class_array)
+         {
+           static u4 multiplicator[10];
+           static int is_initialized = 0;
+
+           java_arrayheader *array = (java_arrayheader*)this;
+           u4 size;
+
+           if (!is_initialized)
+             {
+               multiplicator[ARRAYTYPE_INT] = sizeof(s4);
+               multiplicator[ARRAYTYPE_LONG] = sizeof(s8);
+               multiplicator[ARRAYTYPE_FLOAT] = sizeof(float);
+               multiplicator[ARRAYTYPE_DOUBLE] = sizeof(double);
+               multiplicator[ARRAYTYPE_BYTE] = sizeof(s1);
+               multiplicator[ARRAYTYPE_CHAR] = sizeof(u2);
+               multiplicator[ARRAYTYPE_SHORT] = sizeof(s2);
+               multiplicator[ARRAYTYPE_BOOLEAN] = sizeof(u1);
+               multiplicator[ARRAYTYPE_OBJECT] = sizeof(void*);
+               multiplicator[ARRAYTYPE_ARRAY] = sizeof(void*);
+               is_initialized = 1;
+             }
+           
+           size = sizeof(java_arrayheader)
+             + array->size * multiplicator[array->arraytype];
+
+           new = (java_lang_Object*)heap_allocate(size, false, NULL);
+           memcpy(new, this, size);
+
+           return new;
+         }
+       else
+         {
+           if (! builtin_instanceof ((java_objectheader*) this, class_java_lang_Cloneable) ) {
+               exceptionptr = native_new_and_init (class_java_lang_CloneNotSupportedException);
+               return NULL;
+               }
+       
+       c = this -> header.vftbl -> class;
+       new = (java_lang_Object*) builtin_new (c);
+       if (!new) {
+               exceptionptr = proto_java_lang_OutOfMemoryError;
+               return NULL;
+               }
+
+           memcpy (new, this, c->instancesize);
+           return new;
+         }
+}
+       
+void java_lang_Object_notify (struct java_lang_Object* this)
+{
+       if (runverbose)
+               log_text ("java_lang_Object_notify called");
+
+#ifdef USE_THREADS
+    signal_cond_for_object(&this->header);
+#endif
+}
+
+void java_lang_Object_notifyAll (struct java_lang_Object* this)
+{
+       if (runverbose)
+               log_text ("java_lang_Object_notifyAll called");
+
+#ifdef USE_THREADS
+       broadcast_cond_for_object(&this->header);
+#endif
+}
+
+void java_lang_Object_wait (struct java_lang_Object* this, s8 time)
+{
+       if (runverbose)
+               log_text ("java_lang_Object_wait called");
+
+#ifdef USE_THREADS
+       wait_cond_for_object(&this->header, time);
+#endif
+}
+
+
+/********************************** java.lang.Class **************************************/
+
+
+struct java_lang_Class* java_lang_Class_forName (struct java_lang_String* s)
+{
+       java_chararray *a,*b;
+       u4 i;
+       unicode *u;
+       classinfo *c;
+       
+       if (!s) return NULL;
+       if (!(a = s->value) ) return NULL;
+       b = builtin_newarray_char (s->count);
+       if (!b) return NULL;
+       for (i=0; i<s->count; i++) {
+               if (a->data[s->offset+i]=='.') b->data[i] = '/';
+           else                           b->data[i] = a->data[s->offset+i];
+           }
+       u = unicode_new_u2 (b->data, b->header.size);
+       c = u->class;
+       if (!c) {
+               c = loader_load (u);
+               loader_initclasses ();
+
+               if (!c) {       
+                       exceptionptr = 
+                       native_new_and_init (class_java_lang_ClassNotFoundException);
+       
+                       return NULL;
+                       }
+
+               }
+       
+       use_class_as_object (c);
+       return (java_lang_Class*) c;
+}
+
+struct java_lang_Object* java_lang_Class_newInstance (struct java_lang_Class* this)
+{
+       java_objectheader *o = native_new_and_init ((classinfo*) this);
+       if (!o) {
+               exceptionptr = 
+                       native_new_and_init (class_java_lang_InstantiationException);
+               }
+       return (java_lang_Object*) o;
+}
+
+struct java_lang_String* java_lang_Class_getName (struct java_lang_Class* this)
+{
+       u4 i;
+       classinfo *c = (classinfo*) this;
+       java_lang_String *s = (java_lang_String*) javastring_new(c->name);
+
+       if (!s) return NULL;
+
+       for (i=0; i<s->value->header.size; i++) {
+               if (s->value->data[i] == '/') s->value->data[i] = '.';
+               }
+       
+       return s;
+}
+
+struct java_lang_Class* java_lang_Class_getSuperclass (struct java_lang_Class* this)
+{
+       classinfo *c = ((classinfo*) this) -> super;
+       if (!c) return NULL;
+
+       use_class_as_object (c);
+       return (java_lang_Class*) c;
+}
+
+java_objectarray* java_lang_Class_getInterfaces (struct java_lang_Class* this)
+{
+       classinfo *c = (classinfo*) this;
+       u4 i;
+       java_objectarray *a = builtin_anewarray (c->interfacescount, class_java_lang_Class);
+       if (!a) return NULL;
+       for (i=0; i<c->interfacescount; i++) {
+               use_class_as_object (c->interfaces[i]);
+
+               a->data[i] = (java_objectheader*) c->interfaces[i];
+               }
+       return a;
+}
+
+struct java_lang_ClassLoader* java_lang_Class_getClassLoader (struct java_lang_Class* this)
+{
+       log_text ("java_lang_Class_getClassLoader called");
+       return NULL;
+}
+
+s4 java_lang_Class_isInterface (struct java_lang_Class* this)
+{
+       classinfo *c = (classinfo*) this;
+       if (c->flags & ACC_INTERFACE) return 1;
+       return 0;
+}
+
+/************************************ java.lang.ClassLoader *******************************/
+
+
+struct java_lang_Class* java_lang_ClassLoader_defineClass (struct java_lang_ClassLoader* this, java_bytearray* par1, s4 par2, s4 par3)
+{
+       log_text ("java_lang_ClassLoader_defineClass called");
+       return NULL;
+}
+void java_lang_ClassLoader_resolveClass (struct java_lang_ClassLoader* this, struct java_lang_Class* par1)
+{
+       log_text ("java_lang_ClassLoader_resolveClass called");
+}
+struct java_lang_Class* java_lang_ClassLoader_findSystemClass (struct java_lang_ClassLoader* this, struct java_lang_String* par1)
+{
+       log_text ("java_lang_ClassLoader_findSystemClass called");
+       return NULL;
+}      
+void java_lang_ClassLoader_init (struct java_lang_ClassLoader* this)
+{
+       log_text ("java_lang_ClassLoader_init called");
+}
+struct java_lang_Class* java_lang_ClassLoader_findSystemClass0 (struct java_lang_ClassLoader* this, struct java_lang_String* par1)
+{
+       log_text ("java_lang_ClassLoader_findSystemClass0 called");
+       return NULL;
+}
+
+struct java_lang_Class* java_lang_ClassLoader_defineClass0 (struct java_lang_ClassLoader* this, java_bytearray* par1, s4 par2, s4 par3)
+{
+       log_text ("java_lang_ClassLoader_defineClass0 called");
+       return NULL;
+}
+void java_lang_ClassLoader_resolveClass0 (struct java_lang_ClassLoader* this, struct java_lang_Class* par1)
+{
+       log_text ("java_lang_ClassLoader_resolveClass0 called");
+       return;
+}
+
+/************************************** java.lang.Compiler  *******************************/
+
+void java_lang_Compiler_initialize ()
+{
+       log_text ("java_lang_Compiler_initialize called");
+}
+s4 java_lang_Compiler_compileClass (struct java_lang_Class* par1) 
+{
+       log_text ("java_lang_Compiler_compileClass called");
+       return 0;
+}
+s4 java_lang_Compiler_compileClasses (struct java_lang_String* par1)
+{
+       log_text ("java_lang_Compiler_compileClasses called");
+       return 0;
+}
+struct java_lang_Object* java_lang_Compiler_command (struct java_lang_Object* par1)
+{
+       log_text ("java_lang_Compiler_command called");
+       return NULL;
+}
+void java_lang_Compiler_enable ()
+{
+       log_text ("java_lang_Compiler_enable called");
+}
+void java_lang_Compiler_disable ()
+{
+       log_text ("java_lang_Compiler_disable called");
+}
+
+
+/******************************** java.lang.Double **************************************/
+
+struct java_lang_String* java_lang_Double_toString (double par1)
+{
+       char b[400];
+       sprintf (b, "%-.6g", par1);
+       return (java_lang_String*) javastring_new_char (b);
+}
+struct java_lang_Double* java_lang_Double_valueOf (struct java_lang_String* par1)
+{      
+       float val;
+       java_lang_Double *d = (java_lang_Double*) builtin_new (class_java_lang_Double);
+       if (d) {        
+               sscanf (javastring_tochar((java_objectheader*) par1), "%f", &val);
+               d->value = val;
+               return d;
+       }
+       return NULL;
+}
+s8 java_lang_Double_doubleToLongBits (double par1)
+{
+       s8 l;
+       double d = par1;
+       memcpy ((u1*) &l, (u1*) &d, 8);
+       return l;
+}
+double java_lang_Double_longBitsToDouble (s8 par1)
+{
+       s8 l = par1;
+       double d;
+       memcpy ((u1*) &d, (u1*) &l, 8);
+       return d;
+}
+
+/******************************** java.lang.Float ***************************************/
+
+struct java_lang_String* java_lang_Float_toString (float par1)
+{
+       char b[50];
+       sprintf (b, "%-.6g", (double) par1);
+       return (java_lang_String*) javastring_new_char (b);
+}
+struct java_lang_Float* java_lang_Float_valueOf (struct java_lang_String* par1)
+{
+       float val;
+       java_lang_Float *d = (java_lang_Float*) builtin_new (class_java_lang_Float);
+       if (d) {        
+               sscanf (javastring_tochar((java_objectheader*) par1), "%f", &val);
+               d->value = val;
+               return d;
+       }
+       return NULL;
+}
+s4 java_lang_Float_floatToIntBits (float par1)
+{
+       s4 i;
+       float f = par1;
+       memcpy ((u1*) &i, (u1*) &f, 4);
+       return i;
+}
+float java_lang_Float_intBitsToFloat (s4 par1)
+{
+       s4 i = par1;
+       float f;
+       memcpy ((u1*) &f, (u1*) &i, 4);
+       return f;
+}
+
+
+/******************************** java.lang.Math ****************************************/
+
+double java_lang_Math_sin (double par1)
+{
+       return sin(par1);
+}
+
+double java_lang_Math_cos (double par1)
+{
+       return cos(par1);
+}
+
+double java_lang_Math_tan (double par1)
+{
+       return tan(par1);
+}
+
+double java_lang_Math_asin (double par1)
+{
+       return asin(par1);
+}
+
+double java_lang_Math_acos (double par1)
+{
+       return acos(par1);
+}
+
+double java_lang_Math_atan (double par1)
+{
+       return atan(par1);
+}
+
+double java_lang_Math_exp (double par1)
+{
+       return exp(par1);
+}
+
+double java_lang_Math_log (double par1)
+{
+       if (par1<0.0) {
+               exceptionptr = proto_java_lang_ArithmeticException;
+               return 0.0;
+               }
+       return log(par1);
+}
+
+double java_lang_Math_sqrt (double par1)
+{
+       if (par1<0.0) {
+               exceptionptr = proto_java_lang_ArithmeticException;
+               return 0.0;
+               }
+       return sqrt(par1);
+}
+
+static u8 dbl_nan    = 0xffffffffffffffffL ;
+
+#define DBL_NAN    (*((double*) (&dbl_nan)))
+
+double java_lang_Math_IEEEremainder (double a, double b)
+{
+       double d;
+       if (finite(a) && finite(b)) {
+               d = a / b;
+               if (finite(d))
+                       return a - floor(d) * b;
+               return DBL_NAN;
+               }
+       if (isnan(b))
+               return DBL_NAN;
+       if (finite(a))
+               return a;
+       return DBL_NAN;
+}
+
+double java_lang_Math_ceil (double par1)
+{
+       return ceil(par1);
+}
+
+double java_lang_Math_floor (double par1)
+{
+       return floor(par1);
+}
+
+double java_lang_Math_rint (double par1)
+{
+       panic ("native Methode java_lang_rint not implemented yet");
+       return 0.0;
+}
+
+double java_lang_Math_atan2 (double par1, double par2)
+{
+       return atan2(par1,par2);
+}
+
+double java_lang_Math_pow (double par1, double par2)
+{
+       return pow(par1,par2);
+}
+
+
+/******************************* java.lang.Runtime **************************************/
+
+void java_lang_Runtime_exitInternal (struct java_lang_Runtime* this, s4 par1)
+{
+       cacao_shutdown (par1);
+}
+struct java_lang_Process* java_lang_Runtime_execInternal (struct java_lang_Runtime* this, java_objectarray* par1, java_objectarray* par2)
+{
+       log_text ("java_lang_Runtime_execInternal called");
+       return NULL;
+}
+s8 java_lang_Runtime_freeMemory (struct java_lang_Runtime* this)
+{
+       log_text ("java_lang_Runtime_freeMemory called");
+       return builtin_i2l (0);
+}
+s8 java_lang_Runtime_totalMemory (struct java_lang_Runtime* this)
+{
+       log_text ("java_lang_Runtime_totalMemory called");
+       return builtin_i2l (0);
+}
+void java_lang_Runtime_gc (struct java_lang_Runtime* this)
+{
+       gc_call();
+}
+void java_lang_Runtime_runFinalization (struct java_lang_Runtime* this)
+{
+       log_text ("java_lang_Runtime_runFinalization called");
+}
+void java_lang_Runtime_traceInstructions (struct java_lang_Runtime* this, s4 par1)
+{
+       log_text ("java_lang_Runtime_traceInstructions called");
+}
+void java_lang_Runtime_traceMethodCalls (struct java_lang_Runtime* this, s4 par1)
+{
+       log_text ("java_lang_Runtime_traceMethodCalls called");
+}
+struct java_lang_String* java_lang_Runtime_initializeLinkerInternal (struct java_lang_Runtime* this)
+{      
+       log_text ("java_lang_Runtime_initializeLinkerInternal called");
+       return (java_lang_String*)javastring_new_char(".");
+}
+struct java_lang_String* java_lang_Runtime_buildLibName (struct java_lang_Runtime* this, struct java_lang_String* par1, struct java_lang_String* par2)
+{
+       log_text ("java_lang_Runtime_buildLibName called");
+       return NULL;
+}
+s4 java_lang_Runtime_loadFileInternal (struct java_lang_Runtime* this, struct java_lang_String* par1)
+{
+       log_text ("java_lang_Runtime_loadFileInternal called");
+       return 1;
+}
+
+
+/**************************************** java.lang.SecurityManager ***********************/
+
+java_objectarray* java_lang_SecurityManager_getClassContext (struct java_lang_SecurityManager* this)
+{
+       log_text ("called: java_lang_SecurityManager_getClassContext");
+       return NULL;
+}
+struct java_lang_ClassLoader* java_lang_SecurityManager_currentClassLoader (struct java_lang_SecurityManager* this)
+{
+       log_text ("called: java_lang_SecurityManager_currentClassLoader");
+       return NULL;
+}
+s4 java_lang_SecurityManager_classDepth (struct java_lang_SecurityManager* this, struct java_lang_String* par1)
+{
+       log_text ("called: java_lang_SecurityManager_classDepth");
+       return 0;
+}
+s4 java_lang_SecurityManager_classLoaderDepth (struct java_lang_SecurityManager* this)
+{
+       log_text ("called: java_lang_SecurityManager_classLoaderDepth");
+       return 0;
+}
+
+
+
+/*********************************** java.lang.System ************************************/
+
+s8 java_lang_System_currentTimeMillis ()
+{
+       struct timeval tv;
+
+       (void) gettimeofday(&tv, NULL);
+       return ((s8) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+}
+
+
+void java_lang_System_arraycopy (struct java_lang_Object* source, s4 sp, 
+                                 struct java_lang_Object* dest, s4 dp, s4 len)
+{
+       s4 i;
+       java_arrayheader *s = (java_arrayheader*) source;
+       java_arrayheader *d = (java_arrayheader*) dest;
+
+       if ( (!s) || (!d) ) { 
+               exceptionptr = proto_java_lang_NullPointerException; 
+               return; 
+               }
+       if ( (s->objheader.vftbl->class != class_array) || (d->objheader.vftbl->class != class_array) ) {
+               exceptionptr = proto_java_lang_ArrayStoreException; 
+               return; 
+               }
+               
+       if (s->arraytype != d->arraytype) {
+               exceptionptr = proto_java_lang_ArrayStoreException; 
+               return; 
+               }
+
+       if ((sp<0) || (sp+len > s->size) || (dp<0) || (dp+len > d->size)) {
+               exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; 
+               return; 
+               }
+
+       switch (s->arraytype) {
+       case ARRAYTYPE_BYTE:
+               {
+               java_bytearray *bas = (java_bytearray*) s;
+               java_bytearray *bad = (java_bytearray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) bad->data[dp+i] = bas->data[sp+i];
+               else 
+                       for (i=len-1; i>=0; i--) bad->data[dp+i] = bas->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_BOOLEAN:
+               {
+               java_booleanarray *bas = (java_booleanarray*) s;
+               java_booleanarray *bad = (java_booleanarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) bad->data[dp+i] = bas->data[sp+i];
+               else 
+                       for (i=len-1; i>=0; i--) bad->data[dp+i] = bas->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_CHAR:
+               {
+               java_chararray *cas = (java_chararray*) s;
+               java_chararray *cad = (java_chararray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) cad->data[dp+i] = cas->data[sp+i];
+               else 
+                       for (i=len-1; i>=0; i--) cad->data[dp+i] = cas->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_SHORT:
+               {
+               java_shortarray *sas = (java_shortarray*) s;
+               java_shortarray *sad = (java_shortarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) sad->data[dp+i] = sas->data[sp+i];
+               else
+                       for (i=len-1; i>=0; i--) sad->data[dp+i] = sas->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_INT:
+               {
+               java_intarray *ias = (java_intarray*) s;
+               java_intarray *iad = (java_intarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) iad->data[dp+i] = ias->data[sp+i];
+               else
+                       for (i=len-1; i>=0; i--) iad->data[dp+i] = ias->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_LONG:
+               {
+               java_longarray *las = (java_longarray*) s;
+               java_longarray *lad = (java_longarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) lad->data[dp+i] = las->data[sp+i];
+               else
+                       for (i=len-1; i>=0; i--) lad->data[dp+i] = las->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_FLOAT:
+               {
+               java_floatarray *fas = (java_floatarray*) s;
+               java_floatarray *fad = (java_floatarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) fad->data[dp+i] = fas->data[sp+i];
+               else
+                       for (i=len-1; i>=0; i--) fad->data[dp+i] = fas->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_DOUBLE:
+               {
+               java_doublearray *das = (java_doublearray*) s;
+               java_doublearray *dad = (java_doublearray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) dad->data[dp+i] = das->data[sp+i];
+               else
+                       for (i=len-1; i>=0; i--) dad->data[dp+i] = das->data[sp+i];
+               }
+               break;
+       case ARRAYTYPE_OBJECT:
+               {
+               java_objectarray *oas = (java_objectarray*) s;
+               java_objectarray *oad = (java_objectarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) {
+                               java_objectheader *o = oas->data[sp+i];
+                               if (!builtin_canstore(oad, o)) {
+                                       exceptionptr = proto_java_lang_ArrayStoreException;
+                                       return;
+                                       }
+                               oad->data[dp+i] = o;
+                               }
+               else 
+                       for (i=len-1; i>=0; i--) {
+                               java_objectheader *o = oas->data[sp+i];
+                               if (!builtin_canstore(oad, o)) {
+                                       exceptionptr = proto_java_lang_ArrayStoreException;
+                                       return;
+                                       }
+                               oad->data[dp+i] = o;
+                               }
+               
+               }
+               break;
+       case ARRAYTYPE_ARRAY:
+               {
+               java_arrayarray *aas = (java_arrayarray*) s;
+               java_arrayarray *aad = (java_arrayarray*) d;
+               if (dp<=sp) 
+                       for (i=0; i<len; i++) {
+                               java_arrayheader *o = aas->data[sp+i];
+                               if (!builtin_canstore( (java_objectarray*)aad, 
+                                       (java_objectheader*)o )) {
+                                       exceptionptr = proto_java_lang_ArrayStoreException;
+                                       return;
+                                       }
+                               aad->data[dp+i] = o;
+                               }
+               else
+                       for (i=len-1; i>=0; i--) {
+                               java_arrayheader *o = aas->data[sp+i];
+                               if (!builtin_canstore( (java_objectarray*)aad, 
+                                       (java_objectheader*)o )) {
+                                       exceptionptr = proto_java_lang_ArrayStoreException;
+                                       return;
+                                       }
+                               aad->data[dp+i] = o;
+                               }
+
+               }
+               break;
+
+       default:
+               panic ("Unknown data type for arraycopy");
+       }
+
+}
+
+
+#define MAXPROPS 100
+static int activeprops = 15;
+
+static char *proplist[MAXPROPS][2] = {
+       { "java.class.path", NULL },
+       { "java.home", NULL }, 
+       { "user.home", NULL }, 
+       { "user.name", NULL }, 
+       { "user.dir",  NULL }, 
+       
+       { "java.class.version", "45.3" },
+       { "java.version", "cacao:0.2" },
+       { "java.vendor", "CACAO Team" },
+       { "java.vendor.url", "http://www.complang.tuwien.ac.at/java/cacao/" },
+       { "os.arch", "Alpha" },
+       { "os.name", "Linux/Digital Unix" },
+       { "os.version", "4.0/3.2C/V4.0" },
+       { "path.separator", ":" },
+       { "file.separator", "/" },
+       { "line.separator", "\n" }
+};     
+
+void attach_property (char *name, char *value)
+{
+       if (activeprops >= MAXPROPS) panic ("Too many properties defined");
+       proplist[activeprops][0] = name;
+       proplist[activeprops][1] = value;
+       activeprops++;
+}
+
+
+struct java_util_Properties* java_lang_System_initProperties (struct java_util_Properties* p)
+{
+       u4 i;
+       methodinfo *m;
+#define BUFFERSIZE 200
+       char buffer[BUFFERSIZE];
+       
+       proplist[0][1] = classpath;
+       proplist[1][1] = getenv("JAVAHOME");
+       proplist[2][1] = getenv("HOME");
+       proplist[3][1] = getenv("USER");
+       proplist[4][1] = getcwd(buffer,BUFFERSIZE);
+       
+       if (!p) panic ("initProperties called with NULL-Argument");
+
+       m = class_resolvemethod (
+               p->header.vftbl->class, 
+               unicode_new_char ("put"), 
+               unicode_new_char ("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
+       );
+    if (!m) panic ("Can not find method 'put' for class Properties");
+    
+    for (i=0; i<activeprops; i++) {
+       if (proplist[i][1]==NULL) proplist[i][1]="";
+               
+       asm_calljavamethod (m,  p, 
+                               javastring_new_char(proplist[i][0]),
+                               javastring_new_char(proplist[i][1]),  
+                                       NULL
+                          );
+       }
+
+       return p;
+}
+
+
+
+
+/*********************************** java.lang.Thread ***********************************/
+
+struct java_lang_Thread* java_lang_Thread_currentThread ()
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_currentThread called");
+#ifdef USE_THREADS
+       return (struct java_lang_Thread*)currentThread;
+#else
+       return 0;
+#endif
+}
+
+void java_lang_Thread_yield ()
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_yield called");
+#ifdef USE_THREADS
+       yieldThread();
+#endif
+}
+
+void java_lang_Thread_sleep (s8 par1)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_sleep called");
+#ifdef USE_THREADS
+       yieldThread();
+#endif
+       /* not yet implemented */
+}
+
+void java_lang_Thread_start (struct java_lang_Thread* this)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_start called");
+#ifdef USE_THREADS
+       startThread((thread*)this);
+#endif
+}
+
+s4 java_lang_Thread_isAlive (struct java_lang_Thread* this)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_isAlive called");
+#ifdef USE_THREADS
+       return aliveThread((thread*)this);
+#else
+       return 0;
+#endif
+}
+
+s4 java_lang_Thread_countStackFrames (struct java_lang_Thread* this)
+{
+  log_text ("java_lang_Thread_countStackFrames called");
+  return 0;         /* not yet implemented */
+}
+
+void java_lang_Thread_setPriority0 (struct java_lang_Thread* this, s4 par1)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_setPriority0 called");
+#ifdef USE_THREADS
+  setPriorityThread((thread*)this, par1);
+#endif
+}
+
+void java_lang_Thread_stop0 (struct java_lang_Thread* this, struct java_lang_Object* par1)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_stop0 called");
+#ifdef USE_THREADS
+       if (currentThread == (thread*)this)
+       {
+           log_text("killing");
+           killThread(0);
+           /*
+               exceptionptr = proto_java_lang_ThreadDeath;
+               return;
+           */
+       }
+       else
+       {
+               CONTEXT((thread*)this).flags |= THREAD_FLAGS_KILLED;
+               resumeThread((thread*)this);
+       }
+#endif
+}
+
+void java_lang_Thread_suspend0 (struct java_lang_Thread* this)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_suspend0 called");
+#ifdef USE_THREADS
+       suspendThread((thread*)this);
+#endif
+}
+
+void java_lang_Thread_resume0 (struct java_lang_Thread* this)
+{
+  if (runverbose)
+    log_text ("java_lang_Thread_resume0 called");
+#ifdef USE_THREADS
+       resumeThread((thread*)this);
+#endif
+}
+
+
+
+/************************************ java.lang.Throwable *********************************/
+
+void java_lang_Throwable_printStackTrace0 (struct java_lang_Throwable* this, struct java_io_PrintStream* par1)
+{
+       log_text ("java_lang_Throwable_printStackTrace0 called");
+       return;
+}
+
+struct java_lang_Throwable* java_lang_Throwable_fillInStackTrace (struct java_lang_Throwable *this)
+{
+       this -> detailMessage = 
+         (java_lang_String*) (javastring_new_char ("no backtrace info!") );
+       return this;
+}
+
diff --git a/nat/util.c b/nat/util.c
new file mode 100644 (file)
index 0000000..968496c
--- /dev/null
@@ -0,0 +1,121 @@
+/***************************** nat/util.c **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the native functions for class java.util.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <time.h>
+
+/**************************** java.util.Date **********************************/
+
+
+struct java_lang_String* java_util_Date_toString 
+       (struct java_util_Date* this) 
+{
+       time_t tt;
+       char *buffer;
+       int l;
+       
+       if (!this->valueValid) java_util_Date_computeValue(this);
+       tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+       buffer = ctime (&tt);
+       l = strlen(buffer);
+       while (l>1 && buffer[l-1]=='\n') l--;
+       buffer[l] = '\0';
+       
+       return (java_lang_String*) javastring_new_char( buffer );
+}
+
+
+struct java_lang_String* java_util_Date_toLocaleString 
+       (struct java_util_Date* this)
+{
+       time_t tt;
+       char *buffer;
+       int l;
+
+       if (!this->valueValid) java_util_Date_computeValue(this);
+       tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+       buffer = asctime (localtime(&tt));
+       l = strlen(buffer);
+       while (l>1 && buffer[l-1]=='\n') l--;
+       buffer[l] = '\0';
+
+       return (java_lang_String*) javastring_new_char ( buffer );
+}
+
+struct java_lang_String* java_util_Date_toGMTString 
+       (struct java_util_Date* this)
+{
+       time_t tt;
+       char *buffer;
+       int l;
+
+       if (!this->valueValid) java_util_Date_computeValue(this);
+       tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+
+       buffer = asctime (gmtime(&tt));
+       l = strlen(buffer);
+       while (l>1 && buffer[l-1]=='\n') l--;
+       buffer[l] = '\0';
+       
+       
+       return (java_lang_String*) javastring_new_char ( buffer );
+}
+
+
+
+void java_util_Date_expand (struct java_util_Date* this)
+{
+       struct tm *t;
+       time_t tt;
+       
+       if (this->expanded) return;
+
+       tt = builtin_l2i ( builtin_ldiv(this->value, builtin_i2l(1000) ) );
+       t = gmtime (&tt);
+       this->tm_millis = 
+         builtin_l2i( builtin_lrem (this->value, builtin_i2l(1000) ) );
+       this->tm_sec = t->tm_sec;
+       this->tm_min = t->tm_min;
+       this->tm_hour = t->tm_hour;
+       this->tm_mday = t->tm_mday;
+       this->tm_mon = t->tm_mon;
+       this->tm_wday = t->tm_wday;
+       this->tm_yday = t->tm_yday;
+       this->tm_year = t->tm_year;
+       this->tm_isdst = t->tm_isdst;
+       this->expanded = 1;
+}
+
+void java_util_Date_computeValue (struct java_util_Date* this)
+{
+       struct tm t;
+       
+       if (this->valueValid) return;
+       t.tm_sec = this->tm_sec;
+       t.tm_min = this->tm_min;
+       t.tm_hour = this->tm_hour;
+       t.tm_mday = this->tm_mday;
+       t.tm_mon = this->tm_mon;
+       t.tm_wday = this->tm_wday;
+       t.tm_yday = this->tm_yday;
+       t.tm_year = this->tm_year;
+       t.tm_isdst = this->tm_isdst;
+       this->value = 
+         builtin_ladd( 
+          builtin_lmul( builtin_i2l(mktime(&t)), builtin_i2l(1000)), 
+          builtin_i2l(this->tm_millis)
+         );
+       this->valueValid = 1;   
+}
diff --git a/native.c b/native.c
new file mode 100644 (file)
index 0000000..771ec54
--- /dev/null
+++ b/native.c
@@ -0,0 +1,340 @@
+/****************************** native.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt die Tabellen f"ur die native-methods.
+       Die vom Headerfile-Generator erzeugten -.hh - Dateien werden hier
+       eingebunden, und ebenso alle C-Funktionen, mit denen diese
+       Methoden implementiert werden.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+
+#include "global.h"
+#include "native.h"
+
+#include "builtin.h"
+#include "nativetypes.hh"
+#include "asmpart.h"
+#include "tables.h"
+#include "loader.h"
+
+
+java_objectheader* exceptionptr = NULL;
+
+
+
+static char *classpath;
+
+
+/******************** die f"r die native-Methoden n"otigen Systemklassen *****/
+
+static classinfo *class_java_lang_Class;
+static classinfo *class_java_lang_Cloneable;
+static classinfo *class_java_lang_CloneNotSupportedException;
+static classinfo *class_java_lang_Double;
+static classinfo *class_java_lang_Float;
+static classinfo *class_java_io_IOException;
+static classinfo *class_java_lang_ClassNotFoundException;
+static classinfo *class_java_lang_InstantiationException;
+
+
+
+/************************** alle Funktionen einbinden ************************/ 
+
+#include "nat/lang.c"
+#include "nat/io.c"
+#include "nat/util.c"
+
+
+/********************** Tabellen f"ur die Methoden ***************************/
+
+static struct nativeref {
+       char *classname;
+       char *methodname;
+       char *descriptor;
+       bool isstatic;
+       functionptr func;
+} nativetable [] = {
+
+#include "nativetable.hh"
+
+};
+
+
+#define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
+
+static struct nativecompref {
+       unicode *classname;
+       unicode *methodname;
+       unicode *descriptor;
+       bool isstatic;
+       functionptr func;
+       } nativecomptable [NATIVETABLESIZE];
+
+static bool nativecompdone = false;
+
+
+/*********************** Funktion: native_loadclasses **************************
+
+       L"adt alle Klassen, die die native Methoden zus"atzlich ben"otigen 
+
+*******************************************************************************/
+
+void native_loadclasses()
+{
+       class_java_lang_Cloneable = 
+               loader_load ( unicode_new_char ("java/lang/Cloneable") );
+       class_java_lang_CloneNotSupportedException = 
+               loader_load ( unicode_new_char ("java/lang/CloneNotSupportedException") );
+       class_java_lang_Class =
+               loader_load ( unicode_new_char ("java/lang/Class") );
+       class_java_lang_Double =
+               loader_load ( unicode_new_char ("java/lang/Double") );
+       class_java_lang_Float =
+               loader_load ( unicode_new_char ("java/lang/Float") );
+       class_java_io_IOException = 
+               loader_load ( unicode_new_char ("java/io/IOException") );
+       class_java_lang_ClassNotFoundException =
+               loader_load ( unicode_new_char ("java/lang/ClassNotFoundException") );
+       class_java_lang_InstantiationException=
+               loader_load ( unicode_new_char ("java/lang/InstantiationException") );
+       
+}
+
+/********************* Funktion: native_setclasspath ***************************/
+void native_setclasspath (char *path)
+{
+       classpath = path;
+}
+
+
+/*********************** Funktion: native_findfunction ************************
+
+       Sucht in der Tabelle die passende Methode (muss mit Klassennamen,
+       Methodennamen, Descriptor und 'static'-Status "ubereinstimmen),
+       und gibt den Funktionszeiger darauf zur"uck.
+       Return: Funktionszeiger oder NULL  (wenn es keine solche Methode gibt)
+
+       Anmerkung: Zu Beschleunigung des Suchens werden die als C-Strings
+          vorliegenden Namen/Descriptors in entsprechende unicode-Symbole
+          umgewandelt (beim ersten Aufruf dieser Funktion).
+
+*******************************************************************************/
+
+functionptr native_findfunction (unicode *cname, unicode *mname, 
+                                 unicode *desc, bool isstatic)
+{
+       u4 i;
+       struct nativecompref *n;
+
+       isstatic = isstatic ? true : false;
+
+       if (!nativecompdone) {
+               for (i=0; i<NATIVETABLESIZE; i++) {
+                       nativecomptable[i].classname   = 
+                                       unicode_new_char(nativetable[i].classname);
+                       nativecomptable[i].methodname  = 
+                                       unicode_new_char(nativetable[i].methodname);
+                       nativecomptable[i].descriptor  = 
+                                       unicode_new_char(nativetable[i].descriptor);
+                       nativecomptable[i].isstatic    = 
+                                       nativetable[i].isstatic;
+                       nativecomptable[i].func        = 
+                                       nativetable[i].func;
+                       }
+               nativecompdone = true;
+               }
+
+       for (i=0; i<NATIVETABLESIZE; i++) {
+               n = &(nativecomptable[i]);
+
+               if (cname==n->classname && mname==n->methodname &&
+                   desc==n->descriptor && isstatic==n->isstatic)  return n->func;
+               }
+
+       return NULL;
+}
+
+
+/********************** Funktion: javastring_new *****************************
+
+       Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+       das "ubergebene unicode-Symbol ein. 
+       Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new (unicode *text)
+{
+       u4 i;
+       java_lang_String *s;
+       java_chararray *a;
+       
+       s = (java_lang_String*) builtin_new (class_java_lang_String);
+       a = builtin_newarray_char (text->length);
+
+       if ( (!a) || (!s) ) return NULL;
+
+       for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = text->length;
+
+       return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: javastring_new_char ************************
+
+       Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+       den "ubergebenen C-String ein. 
+       Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new_char (char *text)
+{
+       u4 i;
+       u4 len = strlen(text);
+       java_lang_String *s;
+       java_chararray *a;
+       
+       s = (java_lang_String*) builtin_new (class_java_lang_String);
+       a = builtin_newarray_char (len);
+
+       if ( (!a) || (!s) ) return NULL;
+
+       for (i=0; i<len; i++) a->data[i] = text[i];
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = len;
+
+       return (java_objectheader*) s;
+}
+
+
+/************************* Funktion: javastring_tochar *****************************
+
+       Macht aus einem java-string einen C-String, und liefert den Zeiger
+       darauf zur"uck. 
+       Achtung: Beim n"achsten Aufruf der Funktion wird der vorige String 
+       "uberschrieben
+       
+***********************************************************************************/
+
+#define MAXSTRINGSIZE 1000
+char stringbuffer[MAXSTRINGSIZE];
+
+char *javastring_tochar (java_objectheader *so) 
+{
+       java_lang_String *s = (java_lang_String*) so;
+       java_chararray *a;
+       u4 i;
+       
+       if (!s) return "";
+       a = s->value;
+       if (!a) return "";
+       if (s->count > MAXSTRINGSIZE) return "";
+       for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
+       stringbuffer[i] = '\0';
+       return stringbuffer;
+}
+
+
+/******************** Funktion: native_new_and_init *************************
+
+       Legt ein neues Objekt einer Klasse am Heap an, und ruft automatisch
+       die Initialisierungsmethode auf.
+       Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+                       mehr frei ist.
+                       
+*****************************************************************************/
+
+java_objectheader *native_new_and_init (classinfo *c)
+{
+       methodinfo *m;
+       java_objectheader *o = builtin_new (c);
+
+       if (!o) return NULL;
+       
+       m = class_findmethod (c, 
+                             unicode_new_char ("<init>"), 
+                             unicode_new_char ("()V"));
+       if (!m) {
+               log_text ("warning: class has no instance-initializer:");
+               unicode_sprint (logtext, c->name);
+               dolog();
+               return o;
+               }
+
+       asm_calljavamethod (m, o,NULL,NULL,NULL);
+       return o;
+}
+
+
+/********************* Funktion: literalstring_new ****************************
+
+       erzeugt einen Java-String mit dem angegebenen Text, allerdings nicht
+       auf dem HEAP, sondern in einem anderen Speicherbereich (der String
+       muss dann sp"ater explizit wieder freigegeben werden).
+       Alle Strings, die auf diese Art erzeugt werden, werden in einer
+       gemeinsamen Struktur gespeichert (n"amlich auch "uber die
+       Unicode-Hashtabelle), sodass identische Strings auch wirklich den
+       gleichen Zeiger liefern.
+       
+******************************************************************************/
+
+java_objectheader *literalstring_new (unicode *text)
+{
+       u4 i;
+       java_lang_String *s;
+       java_chararray *a;
+
+       if (text->string) return text->string;
+       
+       a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(text->length-1) );
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = text->length;
+       a -> header.arraytype = ARRAYTYPE_CHAR;
+       for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+
+       s = LNEW (java_lang_String);
+       s -> header.vftbl = class_java_lang_String -> vftbl;
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = text->length;
+
+       unicode_setstringlink (text, (java_objectheader*) s);
+       return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: literalstring_free **************************
+
+       L"oscht einen Java-String wieder aus dem Speicher (wird zu Systemende
+       vom Hashtabellen-Verwalter aufgerufen)
+
+******************************************************************************/
+
+void literalstring_free (java_objectheader* sobj)
+{
+       java_lang_String *s = (java_lang_String*) sobj;
+       java_chararray *a = s->value;
+       
+       LFREE (s, java_lang_String);
+       LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1));
+}
+
+
+
diff --git a/native.h b/native.h
new file mode 100644 (file)
index 0000000..c484642
--- /dev/null
+++ b/native.h
@@ -0,0 +1,35 @@
+/****************************** native.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (PCMDs).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/03/12
+
+*******************************************************************************/
+
+
+extern java_objectheader* exceptionptr;
+
+void native_loadclasses ();
+void native_setclasspath (char *path);
+
+functionptr native_findfunction (unicode *cname, unicode *mname, 
+                                 unicode *desc, bool isstatic);
+
+java_objectheader *javastring_new (unicode *text);
+java_objectheader *javastring_new_char (char *text);
+char *javastring_tochar (java_objectheader *s);
+
+java_objectheader *native_new_and_init (classinfo *c);
+
+java_objectheader *literalstring_new (unicode *text);
+void literalstring_free (java_objectheader*);
+
+void attach_property(char *name, char *value);
diff --git a/ncomp/mcode.c b/ncomp/mcode.c
new file mode 100644 (file)
index 0000000..11fc9a6
--- /dev/null
@@ -0,0 +1,331 @@
+/***************************** comp/mcode.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       This file is an include file for "compiler.c" . It contains (mostly)
+       architecture independent functions for writing instructions into the
+       code area and constants into the data area.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Micheal Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/08/10
+
+
+       All functions assume the following code area / data area layout:
+
+       +-----------+
+       |           |
+       | code area | code area grows to higher addresses
+       |           |
+       +-----------+ <-- start of procedure
+       |           |
+       | data area | data area grows to lower addresses
+       |           |
+       +-----------+
+
+       The functions first write into a temporary code/data area allocated by
+       "mcode_init". "mcode_finish" copies the code and data area into permanent
+       memory. All functions writing values into the data area return the offset
+       relative the begin of the code area (start of procedure).       
+
+*******************************************************************************/
+
+#define MCODEINITSIZE (1<<15)       /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE  (1<<12)       /*  4 Kbyte data area initialization size */
+
+static u1* mcodebase = NULL;        /* base pointer of code area              */
+static s4* mcodeend  = NULL;        /* pointer to end of code area            */
+static int mcodesize;               /* complete size of code area (bytes)     */
+
+static u1* dsegtop = NULL;          /* pointer to top (end) of data area      */
+static int dsegsize;                /* complete size of data area (bytes)     */
+static int dseglen;                 /* used size of data area (bytes)         */
+                                    /* data area grows from top to bottom     */
+
+static jumpref *jumpreferences;     /* list of jumptable target addresses     */
+static branchref *xboundrefs;       /* list of bound check branches           */
+static branchref *xcheckarefs;      /* list of array size check branches      */
+static branchref *xnullrefs;        /* list of null check branches            */
+
+static void mcode_init();           /* allocates code and data area           */
+static void mcode_close();          /* releases temporary storage             */
+static void mcode_finish();         /* makes code and data area permanent and */
+                                    /* updates branch references to code/data */
+
+static s4 dseg_adds4(s4 value);         /* adds an int to data area           */
+static s4 dseg_adds8(s8 value);         /* adds an long to data area          */
+static s4 dseg_addfloat (float value);  /* adds an float to data area         */
+static s4 dseg_adddouble(double value); /* adds an double to data area        */
+
+#if POINTERSIZE==8
+#define dseg_addaddress(value)      dseg_adds8((s8)(value))
+#else
+#define dseg_addaddress(value)      dseg_adds4((s4)(value))
+#endif
+
+static void dseg_addtarget(basicblock *target);
+static void mcode_addreference(basicblock *target, void *branchptr);
+static void mcode_addxboundrefs(void *branchptr);
+static void mcode_addxnullrefs(void *branchptr);
+
+static void dseg_display(s4 *s4ptr);
+
+/* mcode_init allocates and initialises code area, data area and references   */
+
+static void mcode_init()
+{
+       if (!mcodebase) {
+               mcodebase = MNEW (u1, MCODEINITSIZE);
+               mcodesize = MCODEINITSIZE;
+               }
+
+       if (!dsegtop) {
+               dsegtop = MNEW (u1, DSEGINITSIZE);
+               dsegsize = DSEGINITSIZE;
+               dsegtop += dsegsize;
+               }
+
+       dseglen = 0;
+
+       jumpreferences = NULL;
+       xboundrefs = NULL;
+       xnullrefs = NULL;
+}
+
+
+/* mcode_close releases temporary code and data area                          */
+
+static void mcode_close()
+{
+       if (mcodebase) {
+               MFREE (mcodebase, u1, mcodesize);
+               mcodebase = NULL;
+               }
+       if (dsegtop) {
+               MFREE (dsegtop - dsegsize, u1, dsegsize);
+               dsegtop = NULL;
+               }
+}
+
+
+/* mcode_increase doubles code area                                           */
+
+static s4 *mcode_increase(u1 *codeptr)
+{
+       long len;
+
+       len = codeptr - mcodebase;
+       mcodebase = MREALLOC(mcodebase, u1, mcodesize, mcodesize * 2);
+       mcodesize *= 2;
+       mcodeend = (s4*) (mcodebase + mcodesize);
+       return (s4*) (mcodebase + len);
+}
+
+
+/* desg_increase doubles data area                                            */
+
+static void dseg_increase() {
+       u1 *newstorage = MNEW (u1, dsegsize * 2);
+       memcpy ( newstorage + dsegsize, dsegtop - dsegsize, dsegsize);
+       MFREE (dsegtop - dsegsize, u1, dsegsize);
+       dsegtop = newstorage;
+       dsegsize *= 2;
+       dsegtop += dsegsize;
+}
+
+
+static s4 dseg_adds4_increase(s4 value)
+{
+       dseg_increase();
+       *((s4 *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds4(s4 value)
+{
+       s4 *dataptr;
+
+       dseglen += 4;
+       dataptr = (s4 *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adds4_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds8_increase(s8 value)
+{
+       dseg_increase();
+       *((s8 *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adds8(s8 value)
+{
+       s8 *dataptr;
+
+       dseglen = ALIGN (dseglen + 8, 8);
+       dataptr = (s8 *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adds8_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_addfloat_increase(float value)
+{
+       dseg_increase();
+       *((float *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_addfloat(float value)
+{
+       float *dataptr;
+
+       dseglen += 4;
+       dataptr = (float *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_addfloat_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adddouble_increase(double value)
+{
+       dseg_increase();
+       *((double *) (dsegtop - dseglen)) = value;
+       return -dseglen;
+}
+
+
+static s4 dseg_adddouble(double value)
+{
+       double *dataptr;
+
+       dseglen = ALIGN (dseglen + 8, 8);
+       dataptr = (double *) (dsegtop - dseglen);
+       if (dseglen > dsegsize)
+               return dseg_adddouble_increase(value);
+       *dataptr = value;
+       return -dseglen;
+}
+
+
+static void dseg_addtarget(basicblock *target)
+{
+       jumpref *jr = DNEW(jumpref);
+
+       jr->tablepos = dseg_addaddress(NULL);
+       jr->target = target;
+       jr->next = jumpreferences;
+       jumpreferences = jr;
+}
+
+
+static void mcode_addreference(basicblock *target, void *branchptr)
+{
+       s4 branchpos = (u1*) branchptr - mcodebase;
+
+       if (target->mpc >= 0) {
+               gen_resolvebranch((u1*) mcodebase + branchpos, branchpos, target->mpc);
+               }
+       else {
+               branchref *br = DNEW(branchref);
+
+               br->branchpos = branchpos;
+               br->next = target->branchrefs;
+               target->branchrefs= br;
+               }
+}
+
+
+static void mcode_addxboundrefs(void *branchptr)
+{
+       s4 branchpos = (u1*) branchptr - mcodebase;
+
+       branchref *br = DNEW(branchref);
+
+       br->branchpos = branchpos;
+       br->next = xboundrefs;
+       xboundrefs = br;
+}
+
+
+static void mcode_addxcheckarefs(void *branchptr)
+{
+       s4 branchpos = (u1*) branchptr - mcodebase;
+
+       branchref *br = DNEW(branchref);
+
+       br->branchpos = branchpos;
+       br->next = xcheckarefs;
+       xcheckarefs = br;
+}
+
+
+static void mcode_addxnullrefs(void *branchptr)
+{
+       s4 branchpos = (u1*) branchptr - mcodebase;
+
+       branchref *br = DNEW(branchref);
+
+       br->branchpos = branchpos;
+       br->next = xnullrefs;
+       xnullrefs = br;
+}
+
+
+static void mcode_finish(int mcodelen)
+{
+       jumpref *jr;
+       u1 *epoint;
+
+       count_code_len += mcodelen;
+       count_data_len += dseglen;
+
+       dseglen = ALIGN(dseglen, MAX_ALIGN);
+
+       method -> mcodelength = mcodelen + dseglen;
+       method -> mcode = CNEW(u1, mcodelen + dseglen);
+
+       memcpy ( method->mcode, dsegtop - dseglen, dseglen);
+       memcpy ( method->mcode + dseglen, mcodebase, mcodelen);
+
+       method -> entrypoint = epoint = (u1*) (method->mcode + dseglen);
+
+       /* jump table resolving */
+
+       jr = jumpreferences;
+       while (jr != NULL) {
+               *((void**) (epoint + jr->tablepos)) = epoint + jr->target->mpc;
+               jr = jr->next;
+               }
+
+#ifdef CACHE_FLUSH_BLOCK
+       synchronize_caches(method->mcode, (mcodelen>>2));
+#endif
+       
+}
+
+
+static void dseg_display(s4 *s4ptr)
+{
+       int i;
+       
+       printf("  --- dump of datasegment\n");
+       for (i = dseglen; i > 0 ; i -= 4) {
+               printf("-%6x: %8x\n", i, (int)(*s4ptr++));
+               }
+       printf("  --- begin of data segment: %p\n", s4ptr);
+}
diff --git a/ncomp/nblock.c b/ncomp/nblock.c
new file mode 100644 (file)
index 0000000..cae3347
--- /dev/null
@@ -0,0 +1,87 @@
+/***************************** ncomp/nblock.c **********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Basic block handling functions.
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/05
+
+*******************************************************************************/
+
+
+/******************** function determine_basic_blocks **************************
+
+       Scans the JavaVM code of a method and marks each instruction which is the
+       start of a basic block.
+       
+*******************************************************************************/
+
+static void allocate_literals()
+{
+       int  p, nextp;
+       int  opcode, i;
+
+       p = 0;
+       while (p < jcodelength) {
+
+               opcode = jcode[p];
+               nextp = p + jcommandsize[opcode];
+
+               switch (opcode) {
+                       case JAVA_WIDE:
+                               switch (code_get_u1(p + 1)) {
+                                       case JAVA_RET:  nextp = p + 4;
+                                                       break;
+                                       case JAVA_IINC: nextp = p + 6;
+                                                       break;
+                                       default:        nextp = p + 4;
+                                                       break;
+                                       }
+                               break;
+                                                       
+                       case JAVA_LOOKUPSWITCH:
+                               {
+                               s4 num;
+
+                               nextp = ALIGN((p + 1), 4);
+                               num = code_get_u4(nextp + 4);
+                               nextp = nextp + 8 + 8 * num;
+                               break;
+                               }
+
+                       case JAVA_TABLESWITCH:
+                               {
+                               s4 num;
+
+                               nextp = ALIGN ((p + 1),4);
+                               num = code_get_s4(nextp + 4);
+                               num = code_get_s4(nextp + 8) - num;
+                               nextp = nextp + 16 + 4 * num;
+                               break;
+                               }       
+
+                       case JAVA_LDC1:
+                               i = code_get_u1(p+1);
+                               goto pushconstantitem;
+                       case JAVA_LDC2:
+                       case JAVA_LDC2W:
+                               i = code_get_u2(p + 1);
+                       pushconstantitem:
+                               if (class_constanttype(class, i) == CONSTANT_String) {
+                                       unicode *s;
+                                       s = class_getconstant(class, i, CONSTANT_String);
+                                       (void) literalstring_new(s);
+                                       }
+                               break;
+                       } /* end switch */
+
+               p = nextp;
+
+               } /* end while */
+
+}
diff --git a/ncomp/ncomp.h b/ncomp/ncomp.h
new file mode 100644 (file)
index 0000000..e8fe1cd
--- /dev/null
@@ -0,0 +1,93 @@
+/****************************** ncomp.h ****************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       new compiler header file for inclusion in other moduls.
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/05
+
+*******************************************************************************/
+
+/************** compiler switches (are set by main function) ******************/
+
+extern bool runverbose;         /* Das Programm soll w"arend des Laufs alle
+                                   Methodenaufrufe mitprotokollieren */
+extern bool compileverbose;     /* Der Compiler soll sagen, was er macht */
+extern bool showstack;          /* Alle Stackzust"ande ausgeben */
+extern bool showdisassemble;    /* Disassemblerlisting ausgeben */
+extern bool showintermediate;   /* Zwischencode ausgeben */
+extern int  optimizelevel;      /* Optimierungsstufe  (0=keine) */
+
+extern bool checkbounds;        /* Arraygrenzen "uberpr"ufen */
+extern bool checknull;          /* auf Null-Pointer "uberpr"ufen */
+extern bool checkfloats;        /* Fehler bei Fliesskommas abfangen */
+extern bool checksync;          /* Thread-Synchronisation wirklich machen */
+
+extern bool getcompilingtime;   
+extern long compilingtime;      /* CPU-Zeit f"urs "Ubersetzen */
+
+extern int  has_ext_instr_set;  /* has instruction set extensions */
+
+
+extern int count_jit_calls;
+extern int count_methods;
+extern int count_spills;
+extern int count_pcmd_activ;
+extern int count_pcmd_drop;
+extern int count_pcmd_zero;
+extern int count_pcmd_const_store;
+extern int count_pcmd_const_alu;
+extern int count_pcmd_const_bra;
+extern int count_pcmd_load;
+extern int count_pcmd_move;
+extern int count_load_instruction;
+extern int count_pcmd_store;
+extern int count_pcmd_store_comb;
+extern int count_dup_instruction;
+extern int count_pcmd_op;
+extern int count_pcmd_mem;
+extern int count_pcmd_met;
+extern int count_pcmd_bra;
+extern int count_pcmd_table;
+extern int count_pcmd_return;
+extern int count_pcmd_returnx;
+extern int count_max_basic_blocks;
+extern int count_basic_blocks;
+extern int count_max_javainstr;
+extern int count_javainstr;
+extern int count_javacodesize;
+extern int count_javaexcsize;
+extern int count_calls;
+extern int count_tryblocks;
+extern int count_code_len;
+extern int count_data_len;
+extern int count_cstub_len;
+extern int count_nstub_len;
+extern int count_max_new_stack;
+extern int count_upper_bound_new_stack;
+extern int *count_block_stack;
+extern int *count_analyse_iterations;
+extern int *count_method_bb_distribution;
+extern int *count_block_size_distribution;
+extern int *count_store_length;
+extern int *count_store_depth;
+
+/******************************* prototypes ***********************************/
+
+methodptr new_compile (methodinfo *m);  /* compile a method with new compiler */
+
+void ncomp_init();                      /* compiler initialisation            */
+void ncomp_close();                     /* compiler finalisation              */
+
+/*
+u1 *createcompilerstub (methodinfo *m);
+u1 *createnativestub (functionptr f, methodinfo *m);
+
+void removecompilerstub (u1 *stub);
+void removenativestub (u1 *stub);
+*/
diff --git a/ncomp/ncompdef.h b/ncomp/ncompdef.h
new file mode 100644 (file)
index 0000000..c44953f
--- /dev/null
@@ -0,0 +1,1103 @@
+/******************************* ncomp/compdef.h *******************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       defines all the constants and data structures of the compiler 
+       
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Michael Gschwind    EMAIL: cacao@complang.tuwien.ac.at
+                  
+       Last Change: 1997/11/05
+
+*******************************************************************************/
+
+#include "../sysdep/types.h"
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct stackelement stackelement;
+typedef stackelement *stackptr;
+typedef struct basicblock basicblock;
+typedef struct instruction instruction;
+typedef struct subroutineinfo subroutineinfo;
+typedef struct varinfo varinfo;
+typedef struct branchref branchref;
+typedef struct jumpref jumpref;
+typedef varinfo *varinfoptr;
+
+
+/************************** stack element structure ***************************/
+
+/*                    slot types                                              */
+
+#define TYPE_INT   0            /* the stack slot types must numbered in the  */
+#define TYPE_LNG   1            /* same order as the ICMD_Ixxx to ICMD_Axxx   */
+#define TYPE_FLT   2            /* instructions (LOAD and STORE)              */
+#define TYPE_DBL   3            /* integer, long, float, double, address      */
+#define TYPE_ADR   4
+
+#define IS_INT_LNG_TYPE(a)      (!((a)&TYPE_FLT))
+#define IS_FLT_DBL_TYPE(a)      ((a)&TYPE_FLT)
+#define IS_2_WORD_TYPE(a)       ((a)&TYPE_LNG)
+
+
+/*                    flags                                                   */
+
+#define SAVEDVAR   1            /* variable has to survive method invocations */
+#define INMEMORY   2            /* variable stored in memory                  */
+
+/*                    variable types                                          */
+
+#define UNDEFVAR   0            /* stack slot will become temp during regalloc*/
+#define TEMPVAR    1            /* stack slot is temp register                */
+#define STACKVAR   2            /* stack slot is numbered stack slot          */
+#define LOCALVAR   3            /* stack slot is local variable               */
+#define ARGVAR     4            /* stack slot is argument variable            */
+
+struct stackelement {
+       stackptr prev;              /* pointer to next element towards bottom     */
+       int type;                   /* data type of stack element                 */
+       int flags;                  /* flags (SAVED, INMEMORY)                    */
+       int varkind;                /* kind of variable or register               */
+       int varnum;                 /* number of variable                         */
+       int regoff;                 /* register number or memory offset           */
+       };
+
+
+/**************************** instruction structure ***************************/
+
+struct instruction {
+       stackptr dst;               /* stack index of destination operand stack   */
+       u2  opc;                    /* opcode of intermediate code command        */
+       s4  op1;                    /* first operand, usually variable number     */
+
+       union {
+               s4 i;                   /* integer operand    */
+               s8 l;                   /* long operand       */
+               float f;                /* float operand      */
+               double d;               /* double operand     */
+               void *a;                /* address operand    */
+               } val;                  /* immediate constant */
+       };
+
+
+/**************************** basic block structure ***************************/
+/*                    flags                                                   */
+
+#define BBUNDEF    -1
+#define BBREACHED  0
+#define BBFINISHED 1
+
+#define BBTYPE_STD 0            /* standard basic block type                  */
+#define BBTYPE_EXH 1            /* exception handler basic block type         */
+#define BBTYPE_SBR 2            /* subroutine basic block type                */
+
+struct basicblock { 
+       int flags;                  /* used during stack analysis, init with -1   */
+       int type;                   /* basic block type (std, xhandler, subroutine*/
+       int ipc;                    /* intermediate code pc at start of block     */
+       int mpc;                    /* machine code pc at start of block          */
+       stackptr instack;           /* stack at begin of basic block              */
+       stackptr outstack;          /* stack at end of basic block                */
+       int indepth;                /* stack depth at begin of basic block        */
+       int outdepth;               /* stack depth end of basic block             */
+       branchref *branchrefs;      /* list of branches to be patched             */
+       };
+
+
+/************************* pseudo variable structure **************************/
+
+struct varinfo {
+       int type;                   /* basic type of variable                     */
+       int flags;                  /* flags (SAVED, INMEMORY)                    */
+       int regoff;                 /* register number or memory offset           */
+       };
+
+typedef varinfo varinfo5[5];
+
+
+/***************** forward references in branch instructions ******************/
+
+struct branchref {
+       s4 branchpos;               /* patching position in code segment          */
+       branchref *next;            /* next element in branchref list             */
+       };
+
+
+/******************** forward references in tables  ***************************/
+
+struct jumpref {
+       s4 tablepos;                /* patching position in data segment          */
+       basicblock *target;         /* target basic block                         */
+       jumpref *next;              /* next element in jumpref list               */
+       };
+
+
+/********** JavaVM operation codes (sorted) and instruction lengths ***********/
+
+static int stackreq[256];
+
+static int jcommandsize[256] = {
+
+#define JAVA_NOP               0
+#define ICMD_NOP               0
+        1,
+#define JAVA_ACONST_NULL       1
+#define ICMD_ACONST            1        /* op1 = 0, val.a = constant          */
+        1,
+#define JAVA_ICONST_M1         2
+#define ICMD_NULLCHECKPOP      2
+        1,
+#define JAVA_ICONST_0          3
+#define ICMD_ICONST            3        /* op1 = 0, val.i = constant          */
+        1,
+#define JAVA_ICONST_1          4
+        1,
+#define JAVA_ICONST_2          5
+        1,
+#define JAVA_ICONST_3          6
+        1,
+#define JAVA_ICONST_4          7
+        1,
+#define JAVA_ICONST_5          8
+        1,
+#define JAVA_LCONST_0          9
+#define ICMD_LCONST            9        /* op1 = 0, val.l = constant          */
+        1,
+#define JAVA_LCONST_1         10
+#define ICMD_LCMPCONST        10        /* op1 = 0, val.l = constant          */
+        1,
+#define JAVA_FCONST_0         11
+#define ICMD_FCONST           11        /* op1 = 0, val.f = constant          */
+        1,
+#define JAVA_FCONST_1         12
+        1,
+#define JAVA_FCONST_2         13
+        1,
+#define JAVA_DCONST_0         14
+#define ICMD_DCONST           14        /* op1 = 0, val.a = constant          */
+        1,
+#define JAVA_DCONST_1         15
+        1,
+#define JAVA_BIPUSH           16
+        2,
+#define JAVA_SIPUSH           17
+        3,
+#define JAVA_LDC1             18
+        2,
+#define JAVA_LDC2             19
+        3,
+#define JAVA_LDC2W            20
+        3,
+                                        /* order of LOAD instructions must be */
+                                        /* equal to order of TYPE_XXX defines */
+#define JAVA_ILOAD            21
+#define ICMD_ILOAD            21        /* op1 = local variable               */
+        2,                      
+#define JAVA_LLOAD            22
+#define ICMD_LLOAD            22        /* op1 = local variable               */
+        2,
+#define JAVA_FLOAD            23
+#define ICMD_FLOAD            23        /* op1 = local variable               */
+        2,
+#define JAVA_DLOAD            24
+#define ICMD_DLOAD            24        /* op1 = local variable               */
+        2,
+#define JAVA_ALOAD            25
+#define ICMD_ALOAD            25        /* op1 = local variable               */
+        2,
+#define JAVA_ILOAD_0          26
+#define ICMD_IADDCONST        26
+        1,
+#define JAVA_ILOAD_1          27
+#define ICMD_ISUBCONST        27
+        1,
+#define JAVA_ILOAD_2          28
+#define ICMD_IMULCONST        28
+        1,
+#define JAVA_ILOAD_3          29
+#define ICMD_IANDCONST        29
+        1,
+#define JAVA_LLOAD_0          30
+#define ICMD_IORCONST         30
+        1,
+#define JAVA_LLOAD_1          31
+#define ICMD_IXORCONST        31
+        1,
+#define JAVA_LLOAD_2          32
+#define ICMD_ISHLCONST        32
+        1,
+#define JAVA_LLOAD_3          33
+#define ICMD_ISHRCONST        33
+        1,
+#define JAVA_FLOAD_0          34
+#define ICMD_IUSHRCONST       34
+        1,
+#define JAVA_FLOAD_1          35
+        1,
+#define JAVA_FLOAD_2          36
+#define ICMD_LADDCONST        36
+        1,
+#define JAVA_FLOAD_3          37
+#define ICMD_LSUBCONST        37
+        1,
+#define JAVA_DLOAD_0          38
+#define ICMD_LMULCONST        38
+        1,
+#define JAVA_DLOAD_1          39
+#define ICMD_LANDCONST        39
+        1,
+#define JAVA_DLOAD_2          40
+#define ICMD_LORCONST         40
+        1,
+#define JAVA_DLOAD_3          41
+#define ICMD_LXORCONST        41
+        1,
+#define JAVA_ALOAD_0          42
+#define ICMD_LSHLCONST        42
+        1,
+#define JAVA_ALOAD_1          43
+#define ICMD_LSHRCONST        43
+        1,
+#define JAVA_ALOAD_2          44
+#define ICMD_LUSHRCONST       44
+        1,
+#define JAVA_ALOAD_3          45
+        1,
+#define JAVA_IALOAD           46
+#define ICMD_IALOAD           46
+        1,
+#define JAVA_LALOAD           47
+#define ICMD_LALOAD           47
+        1,
+#define JAVA_FALOAD           48
+#define ICMD_FALOAD           48
+        1,
+#define JAVA_DALOAD           49
+#define ICMD_DALOAD           49
+        1,
+#define JAVA_AALOAD           50
+#define ICMD_AALOAD           50
+        1,
+#define JAVA_BALOAD           51
+#define ICMD_BALOAD           51
+        1,
+#define JAVA_CALOAD           52
+#define ICMD_CALOAD           52
+        1,
+#define JAVA_SALOAD           53
+#define ICMD_SALOAD           53
+        1,
+                                        /* order of STORE instructions must be*/
+                                        /* equal to order of TYPE_XXX defines */
+#define JAVA_ISTORE           54
+#define ICMD_ISTORE           54        /* op1 = local variable               */
+        2,
+#define JAVA_LSTORE           55
+#define ICMD_LSTORE           55        /* op1 = local variable               */
+        2,
+#define JAVA_FSTORE           56
+#define ICMD_FSTORE           56        /* op1 = local variable               */
+        2,
+#define JAVA_DSTORE           57
+#define ICMD_DSTORE           57        /* op1 = local variable               */
+        2,
+#define JAVA_ASTORE           58
+#define ICMD_ASTORE           58        /* op1 = local variable               */
+        2,
+#define JAVA_ISTORE_0         59
+#define ICMD_IF_LEQ           59        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_ISTORE_1         60
+#define ICMD_IF_LNE           60        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_ISTORE_2         61
+#define ICMD_IF_LLT           61        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_ISTORE_3         62
+#define ICMD_IF_LGE           62        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_LSTORE_0         63
+#define ICMD_IF_LGT           63        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_LSTORE_1         64
+#define ICMD_IF_LLE           64        /* op1 = target JavaVM pc, val.l      */
+        1,
+#define JAVA_LSTORE_2         65
+#define ICMD_IF_LCMPEQ        65        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_LSTORE_3         66
+#define ICMD_IF_LCMPNE        66        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_FSTORE_0         67
+#define ICMD_IF_LCMPLT        67        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_FSTORE_1         68
+#define ICMD_IF_LCMPGE        68        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_FSTORE_2         69
+#define ICMD_IF_LCMPGT        69        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_FSTORE_3         70
+#define ICMD_IF_LCMPLE        70        /* op1 = target JavaVM pc             */
+        1,
+#define JAVA_DSTORE_0         71
+        1,
+#define JAVA_DSTORE_1         72
+        1,
+#define JAVA_DSTORE_2         73
+        1,
+#define JAVA_DSTORE_3         74
+        1,
+#define JAVA_ASTORE_0         75
+        1,
+#define JAVA_ASTORE_1         76
+        1,
+#define JAVA_ASTORE_2         77
+        1,
+#define JAVA_ASTORE_3         78
+        1,
+#define JAVA_IASTORE          79
+#define ICMD_IASTORE          79
+        1,
+#define JAVA_LASTORE          80
+#define ICMD_LASTORE          80
+        1,
+#define JAVA_FASTORE          81
+#define ICMD_FASTORE          81
+        1,
+#define JAVA_DASTORE          82
+#define ICMD_DASTORE          82
+        1,
+#define JAVA_AASTORE          83
+#define ICMD_AASTORE          83
+        1,
+#define JAVA_BASTORE          84
+#define ICMD_BASTORE          84
+        1,
+#define JAVA_CASTORE          85
+#define ICMD_CASTORE          85
+        1,
+#define JAVA_SASTORE          86
+#define ICMD_SASTORE          86
+        1,
+#define JAVA_POP              87
+#define ICMD_POP              87
+        1,
+#define JAVA_POP2             88
+#define ICMD_POP2             88
+        1,
+#define JAVA_DUP              89
+#define ICMD_DUP              89
+        1,
+#define JAVA_DUP_X1           90
+#define ICMD_DUP_X1           90
+        1,
+#define JAVA_DUP_X2           91
+#define ICMD_DUP_X2           91
+        1,
+#define JAVA_DUP2             92
+#define ICMD_DUP2             92
+        1,
+#define JAVA_DUP2_X1          93
+#define ICMD_DUP2_X1          93
+        1,
+#define JAVA_DUP2_X2          94
+#define ICMD_DUP2_X2          94
+        1,
+#define JAVA_SWAP             95
+#define ICMD_SWAP             95
+        1,
+#define JAVA_IADD             96
+#define ICMD_IADD             96
+        1,
+#define JAVA_LADD             97
+#define ICMD_LADD             97
+        1,
+#define JAVA_FADD             98
+#define ICMD_FADD             98
+        1,
+#define JAVA_DADD             99
+#define ICMD_DADD             99
+        1,
+#define JAVA_ISUB             100
+#define ICMD_ISUB             100
+        1,
+#define JAVA_LSUB             101
+#define ICMD_LSUB             101
+        1,
+#define JAVA_FSUB             102
+#define ICMD_FSUB             102
+        1,
+#define JAVA_DSUB             103
+#define ICMD_DSUB             103
+        1,
+#define JAVA_IMUL             104
+#define ICMD_IMUL             104
+        1,
+#define JAVA_LMUL             105
+#define ICMD_LMUL             105
+        1,
+#define JAVA_FMUL             106
+#define ICMD_FMUL             106
+        1,
+#define JAVA_DMUL             107
+#define ICMD_DMUL             107
+        1,
+#define JAVA_IDIV             108
+#define ICMD_IDIV             108
+        1,
+#define JAVA_LDIV             109
+#define ICMD_LDIV             109
+        1,
+#define JAVA_FDIV             110
+#define ICMD_FDIV             110
+        1,
+#define JAVA_DDIV             111
+#define ICMD_DDIV             111
+        1,
+#define JAVA_IREM             112
+#define ICMD_IREM             112
+        1,
+#define JAVA_LREM             113
+#define ICMD_LREM             113
+        1,
+#define JAVA_FREM             114
+#define ICMD_FREM             114
+        1,
+#define JAVA_DREM             115
+#define ICMD_DREM             115
+        1,
+#define JAVA_INEG             116
+#define ICMD_INEG             116
+        1,
+#define JAVA_LNEG             117
+#define ICMD_LNEG             117
+        1,
+#define JAVA_FNEG             118
+#define ICMD_FNEG             118
+        1,
+#define JAVA_DNEG             119
+#define ICMD_DNEG             119
+        1,
+#define JAVA_ISHL             120
+#define ICMD_ISHL             120
+        1,
+#define JAVA_LSHL             121
+#define ICMD_LSHL             121
+        1,
+#define JAVA_ISHR             122
+#define ICMD_ISHR             122
+        1,
+#define JAVA_LSHR             123
+#define ICMD_LSHR             123
+        1,
+#define JAVA_IUSHR            124
+#define ICMD_IUSHR            124
+        1,
+#define JAVA_LUSHR            125
+#define ICMD_LUSHR            125
+        1,
+#define JAVA_IAND             126
+#define ICMD_IAND             126
+        1,
+#define JAVA_LAND             127
+#define ICMD_LAND             127
+        1,
+#define JAVA_IOR              128
+#define ICMD_IOR              128
+        1,
+#define JAVA_LOR              129
+#define ICMD_LOR              129
+        1,
+#define JAVA_IXOR             130
+#define ICMD_IXOR             130
+        1,
+#define JAVA_LXOR             131
+#define ICMD_LXOR             131
+        1,
+#define JAVA_IINC             132
+#define ICMD_IINC             132   /* op1 = local variable, val.i = constant */
+        3,
+#define JAVA_I2L              133
+#define ICMD_I2L              133
+        1,
+#define JAVA_I2F              134
+#define ICMD_I2F              134
+        1,
+#define JAVA_I2D              135
+#define ICMD_I2D              135
+        1,
+#define JAVA_L2I              136
+#define ICMD_L2I              136
+        1,
+#define JAVA_L2F              137
+#define ICMD_L2F              137
+        1,
+#define JAVA_L2D              138
+#define ICMD_L2D              138
+        1,
+#define JAVA_F2I              139
+#define ICMD_F2I              139
+        1,
+#define JAVA_F2L              140
+#define ICMD_F2L              140
+        1,
+#define JAVA_F2D              141
+#define ICMD_F2D              141
+        1,
+#define JAVA_D2I              142
+#define ICMD_D2I              142
+        1,
+#define JAVA_D2L              143
+#define ICMD_D2L              143
+        1,
+#define JAVA_D2F              144
+#define ICMD_D2F              144
+        1,
+#define JAVA_INT2BYTE         145
+#define ICMD_INT2BYTE         145
+        1,
+#define JAVA_INT2CHAR         146
+#define ICMD_INT2CHAR         146
+        1,
+#define JAVA_INT2SHORT        147
+#define ICMD_INT2SHORT        147
+        1,
+#define JAVA_LCMP             148
+#define ICMD_LCMP             148
+        1,
+#define JAVA_FCMPL            149
+#define ICMD_FCMPL            149
+        1,
+#define JAVA_FCMPG            150
+#define ICMD_FCMPG            150
+        1,
+#define JAVA_DCMPL            151
+#define ICMD_DCMPL            151
+        1,
+#define JAVA_DCMPG            152
+#define ICMD_DCMPG            152
+        1,
+#define JAVA_IFEQ             153
+#define ICMD_IFEQ             153       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IFNE             154
+#define ICMD_IFNE             154       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IFLT             155
+#define ICMD_IFLT             155       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IFGE             156
+#define ICMD_IFGE             156       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IFGT             157
+#define ICMD_IFGT             157       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IFLE             158
+#define ICMD_IFLE             158       /* op1 = target JavaVM pc, val.i      */
+        3,
+#define JAVA_IF_ICMPEQ        159
+#define ICMD_IF_ICMPEQ        159       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ICMPNE        160
+#define ICMD_IF_ICMPNE        160       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ICMPLT        161
+#define ICMD_IF_ICMPLT        161       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ICMPGE        162
+#define ICMD_IF_ICMPGE        162       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ICMPGT        163
+#define ICMD_IF_ICMPGT        163       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ICMPLE        164
+#define ICMD_IF_ICMPLE        164       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ACMPEQ        165
+#define ICMD_IF_ACMPEQ        165       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IF_ACMPNE        166
+#define ICMD_IF_ACMPNE        166       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_GOTO             167
+#define ICMD_GOTO             167       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_JSR              168
+#define ICMD_JSR              168       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_RET              169
+#define ICMD_RET              169       /* op1 = local variable               */
+        2,
+#define JAVA_TABLESWITCH      170
+#define ICMD_TABLESWITCH      170       /* val.a = pointer to s4 table        */
+        0,                              /* length must be computed            */
+#define JAVA_LOOKUPSWITCH     171
+#define ICMD_LOOKUPSWITCH     171       /* val.a = pointer to s4 table        */
+        0,                              /* length must be computed            */
+#define JAVA_IRETURN          172
+#define ICMD_IRETURN          172
+        1,
+#define JAVA_LRETURN          173
+#define ICMD_LRETURN          173
+        1,
+#define JAVA_FRETURN          174
+#define ICMD_FRETURN          174
+        1,
+#define JAVA_DRETURN          175
+#define ICMD_DRETURN          175
+        1,
+#define JAVA_ARETURN          176
+#define ICMD_ARETURN          176
+        1,
+#define JAVA_RETURN           177
+#define ICMD_RETURN           177
+        1,
+#define JAVA_GETSTATIC        178
+#define ICMD_GETSTATIC        178       /* op1 = type, val.a = field adress   */
+        3,
+#define JAVA_PUTSTATIC        179
+#define ICMD_PUTSTATIC        179       /* op1 = type, val.a = field adress   */
+        3,
+#define JAVA_GETFIELD         180
+#define ICMD_GETFIELD         180       /* op1 = type, val.i = field offset   */
+        3,
+#define JAVA_PUTFIELD         181
+#define ICMD_PUTFIELD         181       /* op1 = type, val.i = field offset   */
+        3,
+#define JAVA_INVOKEVIRTUAL    182
+#define ICMD_INVOKEVIRTUAL    182       /* val.a = method info pointer        */
+        3,
+#define JAVA_INVOKESPECIAL    183
+#define ICMD_INVOKESPECIAL    183       /* val.a = method info pointer        */
+        3,
+#define JAVA_INVOKESTATIC     184
+#define ICMD_INVOKESTATIC     184       /* val.a = method info pointer        */
+        3,
+#define JAVA_INVOKEINTERFACE  185
+#define ICMD_INVOKEINTERFACE  185       /* val.a = method info pointer        */
+        5,
+#define ICMD_CHECKASIZE       186       /*                                    */
+        1, /* unused */
+#define JAVA_NEW              187
+#define ICMD_NEW              187       /* op1 = 1, val.a = class pointer     */
+        3,
+#define JAVA_NEWARRAY         188
+#define ICMD_NEWARRAY         188       /* op1 = basic type                   */
+        2,
+#define JAVA_ANEWARRAY        189
+#define ICMD_ANEWARRAY        189       /* op1 = 0, val.a = array pointer     */
+        3,                              /* op1 = 1, val.a = class pointer     */
+#define JAVA_ARRAYLENGTH      190
+#define ICMD_ARRAYLENGTH      190
+        1,
+#define JAVA_ATHROW           191
+#define ICMD_ATHROW           191
+        1,
+#define JAVA_CHECKCAST        192
+#define ICMD_CHECKCAST        192       /* op1 = 0, val.a = array pointer     */
+        3,                              /* op1 = 1, val.a = class pointer     */
+#define JAVA_INSTANCEOF       193
+#define ICMD_INSTANCEOF       193       /* op1 = 0, val.a = array pointer     */
+        3,                              /* op1 = 1, val.a = class pointer     */
+#define JAVA_MONITORENTER     194
+#define ICMD_MONITORENTER     194
+        1,
+#define JAVA_MONITOREXIT      195
+#define ICMD_MONITOREXIT      195
+        1,
+#define JAVA_WIDE             196
+        0,       /* length must be computed */
+#define JAVA_MULTIANEWARRAY   197
+#define ICMD_MULTIANEWARRAY   197       /* op1 = dimension, val.a = array     */
+        4,                              /* pointer                            */
+#define JAVA_IFNULL           198
+#define ICMD_IFNULL           198       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_IFNONNULL        199
+#define ICMD_IFNONNULL        199       /* op1 = target JavaVM pc             */
+        3,
+#define JAVA_GOTO_W           200
+        5,
+#define JAVA_JSR_W            201
+        5,
+#define JAVA_BREAKPOINT       202
+        1,
+
+            1,1,1,1,1,1,1,1,            /* unused */
+        1,1,1,1,1,1,1,1,1,1,
+        1,1,1,1,1,1,1,1,1,1,
+        1,1,1,1,1,1,1,1,1,1,
+        1,1,1,1,1,1,1,1,1,1,
+        1,1,1,1,1
+    };
+
+#define ICMD_BUILTIN3         253       /* internal opcode */
+#define ICMD_BUILTIN2         254       /* internal opcode */
+#define ICMD_BUILTIN1         255       /* internal opcode */
+
+
+/******************* description of JavaVM instructions ***********************/
+
+typedef struct {
+       u1 opcode;
+       u1 type_s1;
+       u1 type_s2;
+       u1 type_d;      
+       functionptr builtin;
+       bool supported;
+       bool isfloat;
+} stdopdescriptor;
+
+static stdopdescriptor *stdopdescriptors[256];
+
+static stdopdescriptor stdopdescriptortable[] = {
+       { JAVA_IADD,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_ISUB,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_IMUL,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_ISHL,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_ISHR,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_IUSHR,  TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_IAND,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_IOR,    TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_IXOR,   TYPE_INT, TYPE_INT, TYPE_INT, NULL, true, false },
+       { JAVA_INEG,   TYPE_INT, TYPE_VOID,TYPE_INT, NULL, true, false },
+
+       { JAVA_LADD,   TYPE_LONG, TYPE_LONG, TYPE_LONG, 
+              (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { JAVA_LSUB,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { JAVA_LMUL,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MULDIV, false },
+       { JAVA_LSHL,   TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { JAVA_LSHR,   TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { JAVA_LUSHR,  TYPE_LONG, TYPE_INT,  TYPE_LONG,
+              (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
+       { JAVA_LAND,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_land, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { JAVA_LOR,    TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { JAVA_LXOR,   TYPE_LONG, TYPE_LONG, TYPE_LONG,
+              (functionptr) builtin_lxor, SUPPORT_LONG && SUPPORT_LONG_LOG, false },
+       { JAVA_LNEG,   TYPE_LONG, TYPE_VOID, TYPE_LONG,
+              (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, false },
+       { JAVA_LCMP,   TYPE_LONG, TYPE_LONG, TYPE_INT,
+              (functionptr) builtin_lcmp, SUPPORT_LONG && SUPPORT_LONG_CMP, false },
+
+       { JAVA_FADD,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fadd, SUPPORT_FLOAT, true },
+       { JAVA_FSUB,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fsub, SUPPORT_FLOAT, true },
+       { JAVA_FMUL,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fmul, SUPPORT_FLOAT, true },
+       { JAVA_FDIV,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_fdiv, SUPPORT_FLOAT, true },
+       { JAVA_FREM,   TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, 
+              (functionptr) builtin_frem, SUPPORT_FLOAT, true },
+       { JAVA_FNEG,   TYPE_FLOAT, TYPE_VOID,  TYPE_FLOAT, 
+              (functionptr) builtin_fneg, SUPPORT_FLOAT, true },
+       { JAVA_FCMPL,  TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,   
+              (functionptr) builtin_fcmpl, SUPPORT_FLOAT, true },
+       { JAVA_FCMPG,  TYPE_FLOAT, TYPE_FLOAT, TYPE_INT,   
+              (functionptr) builtin_fcmpg, SUPPORT_FLOAT, true },
+
+       { JAVA_DADD,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dadd, SUPPORT_DOUBLE, true },
+       { JAVA_DSUB,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dsub, SUPPORT_DOUBLE, true },
+       { JAVA_DMUL,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_dmul, SUPPORT_DOUBLE, true },
+       { JAVA_DDIV,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_ddiv, SUPPORT_DOUBLE, true },
+       { JAVA_DREM,   TYPE_DOUBLE, TYPE_DOUBLE, TYPE_DOUBLE, 
+              (functionptr) builtin_drem, SUPPORT_DOUBLE, true },
+       { JAVA_DNEG,   TYPE_DOUBLE, TYPE_VOID,  TYPE_DOUBLE, 
+              (functionptr) builtin_dneg, SUPPORT_DOUBLE, true },
+       { JAVA_DCMPL,  TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, 
+              (functionptr) builtin_dcmpl, SUPPORT_DOUBLE, true },
+       { JAVA_DCMPG,  TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, 
+              (functionptr) builtin_dcmpg, SUPPORT_DOUBLE, true },
+
+       { JAVA_INT2BYTE, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { JAVA_INT2CHAR, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { JAVA_INT2SHORT, TYPE_INT, TYPE_VOID, TYPE_INT, NULL, true,false },
+       { JAVA_I2L,    TYPE_INT,  TYPE_VOID, TYPE_LONG,   
+           (functionptr) builtin_i2l, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+       { JAVA_I2F,    TYPE_INT,  TYPE_VOID, TYPE_FLOAT,  
+              (functionptr) builtin_i2f, SUPPORT_FLOAT, true },
+       { JAVA_I2D,    TYPE_INT,  TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_i2d, SUPPORT_DOUBLE, true },
+       { JAVA_L2I,    TYPE_LONG, TYPE_VOID, TYPE_INT,    
+              (functionptr) builtin_l2i, SUPPORT_LONG && SUPPORT_LONG_ICVT, false },
+       { JAVA_L2F,    TYPE_LONG, TYPE_VOID, TYPE_FLOAT,  
+              (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
+       { JAVA_L2D,    TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
+       { JAVA_F2I,    TYPE_FLOAT, TYPE_VOID, TYPE_INT,   
+              (functionptr) builtin_f2i, SUPPORT_FLOAT, true },
+       { JAVA_F2L,    TYPE_FLOAT, TYPE_VOID, TYPE_LONG,   
+              (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+       { JAVA_F2D,    TYPE_FLOAT, TYPE_VOID, TYPE_DOUBLE, 
+              (functionptr) builtin_f2d, SUPPORT_FLOAT && SUPPORT_DOUBLE, true },
+       { JAVA_D2I,    TYPE_DOUBLE, TYPE_VOID, TYPE_INT,   
+              (functionptr) builtin_d2i, SUPPORT_DOUBLE, true },
+       { JAVA_D2L,    TYPE_DOUBLE, TYPE_VOID, TYPE_LONG,   
+              (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_FCVT, true },
+       { JAVA_D2F,    TYPE_DOUBLE, TYPE_VOID, TYPE_FLOAT, 
+              (functionptr) builtin_d2f, SUPPORT_DOUBLE && SUPPORT_FLOAT, true },
+       
+};
+
+static char *icmd_names[256] = {
+       "NOP          ", /*               0 */
+       "ACONST       ", /*               1 */
+       "NULLCHECKPOP ", /* ICONST_M1     2 */
+       "ICONST       ", /*               3 */
+       "UNDEF__4     ", /* ICONST_1      4 */
+       "UNDEF__5     ", /* ICONST_2      5 */
+       "UNDEF__6     ", /* ICONST_3      6 */
+       "UNDEF__7     ", /* ICONST_4      7 */
+       "UNDEF__8     ", /* ICONST_5      8 */
+       "LCONST       ", /*               9 */
+       "LCMPCONST    ", /* LCONST_1     10 */
+       "FCONST       ", /*              11 */
+       "UNDEF_12     ", /* FCONST_1     12 */
+       "UNDEF_13     ", /* FCONST_2     13 */
+       "DCONST       ", /*              14 */
+       "UNDEF_15     ", /* DCONST_1     15 */
+       "UNDEF_16     ", /* BIPUSH       16 */
+       "UNDEF_17     ", /* SIPUSH       17 */
+       "UNDEF_18     ", /* LDC1         18 */
+       "UNDEF_19     ", /* LDC2         19 */
+       "UNDEF_20     ", /* LDC2W        20 */
+       "ILOAD        ", /*              21 */
+       "LLOAD        ", /*              22 */
+       "FLOAD        ", /*              23 */
+       "DLOAD        ", /*              24 */
+       "ALOAD        ", /*              25 */
+       "IADDCONST    ", /* ILOAD_0      26 */
+       "ISUBCONST    ", /* ILOAD_1      27 */
+       "IMULCONST    ", /* ILOAD_2      28 */
+       "IANDCONST    ", /* ILOAD_3      29 */
+       "IORCONST     ", /* LLOAD_0      30 */
+       "IXORCONST    ", /* LLOAD_1      31 */
+       "ISHLCONST    ", /* LLOAD_2      32 */
+       "ISHRCONST    ", /* LLOAD_3      33 */
+       "IUSHRCONST   ", /* FLOAD_0      34 */
+       "UNDEF_35     ", /* FLOAD_1      35 */
+       "LADDCONST    ", /* FLOAD_2      36 */
+       "LSUBCONST    ", /* FLOAD_3      37 */
+       "LMULCONST    ", /* DLOAD_0      38 */
+       "LANDCONST    ", /* DLOAD_1      39 */
+       "LORCONST     ", /* DLOAD_2      40 */
+       "LXORCONST    ", /* DLOAD_3      41 */
+       "LSHLCONST    ", /* ALOAD_0      42 */
+       "LSHRCONST    ", /* ALOAD_1      43 */
+       "LUSHRCONST   ", /* ALOAD_2      44 */
+       "UNDEF_45     ", /* ALOAD_3      45 */
+       "IALOAD       ", /*              46 */
+       "LALOAD       ", /*              47 */
+       "FALOAD       ", /*              48 */
+       "DALOAD       ", /*              49 */
+       "AALOAD       ", /*              50 */
+       "BALOAD       ", /*              51 */
+       "CALOAD       ", /*              52 */
+       "SALOAD       ", /*              53 */
+       "ISTORE       ", /*              54 */
+       "LSTORE       ", /*              55 */
+       "FSTORE       ", /*              56 */
+       "DSTORE       ", /*              57 */
+       "ASTORE       ", /*              58 */
+       "IF_LEQ       ", /* ISTORE_0     59 */
+       "IF_LNE       ", /* ISTORE_1     60 */
+       "IF_LLT       ", /* ISTORE_2     61 */
+       "IF_LGE       ", /* ISTORE_3     62 */
+       "IF_LGT       ", /* LSTORE_0     63 */
+       "IF_LLE       ", /* LSTORE_1     64 */
+       "IF_LCMPEQ    ", /* LSTORE_2     65 */
+       "IF_LCMPNE    ", /* LSTORE_3     66 */
+       "IF_LCMPLT    ", /* FSTORE_0     67 */
+       "IF_LCMPGE    ", /* FSTORE_1     68 */
+       "IF_LCMPGT    ", /* FSTORE_2     69 */
+       "IF_LCMPLE    ", /* FSTORE_3     70 */
+       "UNDEF_71     ", /* DSTORE_0     71 */
+       "UNDEF_72     ", /* DSTORE_1     72 */
+       "UNDEF_73     ", /* DSTORE_2     73 */
+       "UNDEF_74     ", /* DSTORE_3     74 */
+       "UNDEF_75     ", /* ASTORE_0     75 */
+       "UNDEF_76     ", /* ASTORE_1     76 */
+       "UNDEF_77     ", /* ASTORE_2     77 */
+       "UNDEF_78     ", /* ASTORE_3     78 */
+       "IASTORE      ", /*              79 */
+       "LASTORE      ", /*              80 */
+       "FASTORE      ", /*              81 */
+       "DASTORE      ", /*              82 */
+       "AASTORE      ", /*              83 */
+       "BASTORE      ", /*              84 */
+       "CASTORE      ", /*              85 */
+       "SASTORE      ", /*              86 */
+       "POP          ", /*              87 */
+       "POP2         ", /*              88 */
+       "DUP          ", /*              89 */
+       "DUP_X1       ", /*              90 */
+       "DUP_X2       ", /*              91 */
+       "DUP2         ", /*              92 */
+       "DUP2_X1      ", /*              93 */
+       "DUP2_X2      ", /*              94 */
+       "SWAP         ", /*              95 */
+       "IADD         ", /*              96 */
+       "LADD         ", /*              97 */
+       "FADD         ", /*              98 */
+       "DADD         ", /*              99 */
+       "ISUB         ", /*             100 */
+       "LSUB         ", /*             101 */
+       "FSUB         ", /*             102 */
+       "DSUB         ", /*             103 */
+       "IMUL         ", /*             104 */
+       "LMUL         ", /*             105 */
+       "FMUL         ", /*             106 */
+       "DMUL         ", /*             107 */
+       "IDIV         ", /*             108 */
+       "LDIV         ", /*             109 */
+       "FDIV         ", /*             110 */
+       "DDIV         ", /*             111 */
+       "IREM         ", /*             112 */
+       "LREM         ", /*             113 */
+       "FREM         ", /*             114 */
+       "DREM         ", /*             115 */
+       "INEG         ", /*             116 */
+       "LNEG         ", /*             117 */
+       "FNEG         ", /*             118 */
+       "DNEG         ", /*             119 */
+       "ISHL         ", /*             120 */
+       "LSHL         ", /*             121 */
+       "ISHR         ", /*             122 */
+       "LSHR         ", /*             123 */
+       "IUSHR        ", /*             124 */
+       "LUSHR        ", /*             125 */
+       "IAND         ", /*             126 */
+       "LAND         ", /*             127 */
+       "IOR          ", /*             128 */
+       "LOR          ", /*             129 */
+       "IXOR         ", /*             130 */
+       "LXOR         ", /*             131 */
+       "IINC         ", /*             132 */
+       "I2L          ", /*             133 */
+       "I2F          ", /*             134 */
+       "I2D          ", /*             135 */
+       "L2I          ", /*             136 */
+       "L2F          ", /*             137 */
+       "L2D          ", /*             138 */
+       "F2I          ", /*             139 */
+       "F2L          ", /*             140 */
+       "F2D          ", /*             141 */
+       "D2I          ", /*             142 */
+       "D2L          ", /*             143 */
+       "D2F          ", /*             144 */
+       "INT2BYTE     ", /*             145 */
+       "INT2CHAR     ", /*             146 */
+       "INT2SHORT    ", /*             147 */
+       "LCMP         ", /*             148 */
+       "FCMPL        ", /*             149 */
+       "FCMPG        ", /*             150 */
+       "DCMPL        ", /*             151 */
+       "DCMPG        ", /*             152 */
+       "IFEQ         ", /*             153 */
+       "IFNE         ", /*             154 */
+       "IFLT         ", /*             155 */
+       "IFGE         ", /*             156 */
+       "IFGT         ", /*             157 */
+       "IFLE         ", /*             158 */
+       "IF_ICMPEQ    ", /*             159 */
+       "IF_ICMPNE    ", /*             160 */
+       "IF_ICMPLT    ", /*             161 */
+       "IF_ICMPGE    ", /*             162 */
+       "IF_ICMPGT    ", /*             163 */
+       "IF_ICMPLE    ", /*             164 */
+       "IF_ACMPEQ    ", /*             165 */
+       "IF_ACMPNE    ", /*             166 */
+       "GOTO         ", /*             167 */
+       "JSR          ", /*             168 */
+       "RET          ", /*             169 */
+       "TABLESWITCH  ", /*             170 */
+       "LOOKUPSWITCH ", /*             171 */
+       "IRETURN      ", /*             172 */
+       "LRETURN      ", /*             173 */
+       "FRETURN      ", /*             174 */
+       "DRETURN      ", /*             175 */
+       "ARETURN      ", /*             176 */
+       "RETURN       ", /*             177 */
+       "GETSTATIC    ", /*             178 */
+       "PUTSTATIC    ", /*             179 */
+       "GETFIELD     ", /*             180 */
+       "PUTFIELD     ", /*             181 */
+       "INVOKEVIRTUAL", /*             182 */
+       "INVOKESPECIAL", /*             183 */
+       "INVOKESTATIC ", /*             184 */
+       "INVOKEINTERFACE",/*            185 */
+       "CHECKASIZE   ", /* UNDEF186    186 */
+       "NEW          ", /*             187 */
+       "NEWARRAY     ", /*             188 */
+       "ANEWARRAY    ", /*             189 */
+       "ARRAYLENGTH  ", /*             190 */
+       "ATHROW       ", /*             191 */
+       "CHECKCAST    ", /*             192 */
+       "INSTANCEOF   ", /*             193 */
+       "MONITORENTER ", /*             194 */
+       "MONITOREXIT  ", /*             195 */
+       "UNDEF196     ", /* WIDE        196 */
+       "MULTIANEWARRAY",/*             197 */
+       "IFNULL       ", /*             198 */
+       "IFNONNULL    ", /*             199 */
+       "UNDEF200     ", /* GOTO_W      200 */
+       "UNDEF201     ", /* JSR_W       201 */
+       "UNDEF202     ", /* BREAKPOINT  202 */
+
+                             "UNDEF203","UNDEF204","UNDEF205",
+       "UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
+       "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+       "UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
+       "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+       "UNDEF226","UNDEF227","UNDEF228","UNDEF229","UNDEF230",
+       "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+       "UNDEF236","UNDEF237","UNDEF238","UNDEF239","UNDEF240",
+       "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+       "UNDEF246","UNDEF247","UNDEF248","UNDEF249","UNDEF250",
+       "UNDEF251","UNDEF252",
+       "BUILTIN3     ", /*             253 */
+       "BUILTIN2     ", /*             254 */
+       "BUILTIN1     "  /*             255 */
+    };
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES   0         /* reserved register for OS or code generator     */
+#define REG_RET   1         /* return value register                          */
+#define REG_EXC   2         /* exception value register                       */
+#define REG_SAV   3         /* (callee) saved register                        */
+#define REG_TMP   4         /* scratch temporary register (caller saved)      */
+#define REG_ARG   5         /* argument register (caller saved)               */
+
+#define REG_END   -1        /* last entry in tables                           */
+#define PARAMMODE_NUMBERED  0 
+#define PARAMMODE_STUFFED   1
+
+/***************************** register info block ****************************/
+
+extern int nregdescint[];    /* description of integer registers              */
+extern int nregdescfloat[];  /* description of floating point registers       */
+
+extern int nreg_parammode;
+
+void asm_handle_exception();
+void asm_handle_nat_exception();
diff --git a/ncomp/nparse.c b/ncomp/nparse.c
new file mode 100644 (file)
index 0000000..993e305
--- /dev/null
@@ -0,0 +1,979 @@
+/****************************** ncomp/nparse.c *********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Parser for JavaVM to intermediate code translation
+       
+       Author: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/05/07
+
+*******************************************************************************/
+
+#include "math.h"
+
+/*********************** function allocate_literals ****************************
+
+       Scans the JavaVM code of a method and allocates string literals. Needed
+       to generate the same addresses as the old JIT compiler.
+       
+*******************************************************************************/
+
+static void allocate_literals()
+{
+       int     p, nextp;
+       int     opcode, i;
+       s4      num;
+       unicode *s;
+
+       for (p = 0; p < jcodelength; p = nextp) {
+
+               opcode = jcode[p];
+               nextp = p + jcommandsize[opcode];
+
+               switch (opcode) {
+                       case JAVA_WIDE:
+                               if (code_get_u1(p + 1) == JAVA_IINC)
+                                       nextp = p + 6;
+                               else
+                                       nextp = p + 4;
+                               break;
+                                                       
+                       case JAVA_LOOKUPSWITCH:
+                               nextp = ALIGN((p + 1), 4);
+                               num = code_get_u4(nextp + 4);
+                               nextp = nextp + 8 + 8 * num;
+                               break;
+
+                       case JAVA_TABLESWITCH:
+                               nextp = ALIGN ((p + 1),4);
+                               num = code_get_s4(nextp + 4);
+                               num = code_get_s4(nextp + 8) - num;
+                               nextp = nextp + 16 + 4 * num;
+                               break;
+
+                       case JAVA_LDC1:
+                               i = code_get_u1(p+1);
+                               goto pushconstantitem;
+                       case JAVA_LDC2:
+                       case JAVA_LDC2W:
+                               i = code_get_u2(p + 1);
+                       pushconstantitem:
+                               if (class_constanttype(class, i) == CONSTANT_String) {
+                                       s = class_getconstant(class, i, CONSTANT_String);
+                                       (void) literalstring_new(s);
+                                       }
+                               break;
+                       } /* end switch */
+               } /* end while */
+}
+
+
+
+/*******************************************************************************
+
+       function 'parse' scans the JavaVM code and generates intermediate code
+
+       During parsing the block index table is used to store at bit pos 0
+       a flag which marks basic block starts and at position 1 to 31 the
+       intermediate instruction index. After parsing the block index table
+       is scanned, for marked positions a block is generated and the block
+       number is stored in the block index table.
+
+*******************************************************************************/
+
+/* intermediate code generating macros */
+
+#define PINC           iptr++;ipc++
+#define LOADCONST_I(v) iptr->opc=ICMD_ICONST;iptr->op1=0;iptr->val.i=(v);PINC
+#define LOADCONST_L(v) iptr->opc=ICMD_LCONST;iptr->op1=0;iptr->val.l=(v);PINC
+#define LOADCONST_F(v) iptr->opc=ICMD_FCONST;iptr->op1=0;iptr->val.f=(v);PINC
+#define LOADCONST_D(v) iptr->opc=ICMD_DCONST;iptr->op1=0;iptr->val.d=(v);PINC
+#define LOADCONST_A(v) iptr->opc=ICMD_ACONST;iptr->op1=0;iptr->val.a=(v);PINC
+#define OP(o)          iptr->opc=(o);iptr->op1=0;iptr->val.l=0;PINC
+#define OP1(o,o1)      iptr->opc=(o);iptr->op1=(o1);iptr->val.l=(0);PINC
+#define OP2I(o,o1,v)   iptr->opc=(o);iptr->op1=(o1);iptr->val.i=(v);PINC
+#define OP2A(o,o1,v)   iptr->opc=(o);iptr->op1=(o1);iptr->val.a=(v);PINC
+#define BUILTIN1(v,t)  isleafmethod=false;iptr->opc=ICMD_BUILTIN1;iptr->op1=t;\
+                       iptr->val.a=(v);PINC
+#define BUILTIN2(v,t)  isleafmethod=false;iptr->opc=ICMD_BUILTIN2;iptr->op1=t;\
+                       iptr->val.a=(v);PINC
+#define BUILTIN3(v,t)  isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
+                       iptr->val.a=(v);PINC
+
+
+/* block generating and checking macros */
+
+#define block_insert(i)    {if(!(block_index[i]&1))\
+                               {b_count++;block_index[i] |= 1;}}
+#define bound_check(i)     {if((i< 0) || (i>=jcodelength)) \
+                               panic("branch target out of code-boundary");}
+#define bound_check1(i)    {if((i< 0) || (i>jcodelength)) \
+                               panic("branch target out of code-boundary");}
+
+
+static void parse()
+{
+       int  p;                     /* java instruction counter                   */
+       int  nextp;                 /* start of next java instruction             */
+       int  opcode;                /* java opcode                                */
+       int  i;                     /* temporary for different uses (counters)    */
+       int  ipc = 0;               /* intermediate instruction counter           */
+       int  b_count = 0;           /* basic block counter                        */
+       int  s_count = 0;           /* stack element counter                      */
+       bool blockend = false;      /* true if basic block end has reached        */
+       bool iswide = false;        /* true if last instruction was a wide        */
+       instruction *iptr;          /* current pointer into instruction array     */
+
+
+       /* allocate instruction array and block index table */
+       
+       /* 1 additional for end ipc and 3 for loop unrolling */
+       
+       block_index = DMNEW(int, jcodelength + 3);
+
+       /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
+       /* additional MONITOREXITS are reached by branches which are 3 bytes */
+       
+       iptr = instr = DMNEW(instruction, jcodelength + 5);
+       
+       /* initialize block_index table (unrolled four times) */
+
+       {
+       int *ip;
+       
+       for (i = 0, ip = block_index; i <= jcodelength; i += 4, ip += 4) {
+               ip[0] = 0;
+               ip[1] = 0;
+               ip[2] = 0;
+               ip[3] = 0;
+               }
+       }
+
+       /* compute branch targets of exception table */
+
+       for (i = 0; i < exceptiontablelength; i++) {
+               p = extable[i].startpc;
+               bound_check(p);
+               block_insert(p);
+               p = extable[i].endpc;
+               bound_check1(p);
+               if (p < jcodelength)
+                       block_insert(p);
+               p = extable[i].handlerpc;
+               bound_check(p);
+               block_insert(p);
+               }
+
+       s_count = 1 + exceptiontablelength; /* initialize stack element counter   */
+
+       if (runverbose) {
+/*             isleafmethod=false; */
+               }
+
+#ifdef USE_THREADS
+       if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
+               isleafmethod=false;
+               }                       
+#endif
+
+       /* scan all java instructions */
+
+       for (p = 0; p < jcodelength; p = nextp) {
+
+               opcode = code_get_u1 (p);           /* fetch op code                  */
+
+               block_index[p] |= (ipc << 1);       /* store intermediate count       */
+
+               if (blockend) {
+                       block_insert(p);                /* start new block                */
+                       blockend = false;
+                       }
+
+               nextp = p + jcommandsize[opcode];   /* compute next instruction start */
+               s_count += stackreq[opcode];            /* compute stack element count    */
+
+               switch (opcode) {
+
+                       case JAVA_NOP:
+                               break;
+
+                       /* pushing constants onto the stack p */
+
+                       case JAVA_BIPUSH:
+                               LOADCONST_I(code_get_s1(p+1));
+                               break;
+
+                       case JAVA_SIPUSH:
+                               LOADCONST_I(code_get_s2(p+1));
+                               break;
+
+                       case JAVA_LDC1:
+                               i = code_get_u1(p+1);
+                               goto pushconstantitem;
+                       case JAVA_LDC2:
+                       case JAVA_LDC2W:
+                               i = code_get_u2(p + 1);
+
+                       pushconstantitem:
+
+                               if (i >= class->cpcount) 
+                                       panic ("Attempt to access constant outside range");
+
+                               switch (class->cptags[i]) {
+                                       case CONSTANT_Integer:
+                                               LOADCONST_I(((constant_integer*)
+                                                            (class->cpinfos[i]))->value);
+                                               break;
+                                       case CONSTANT_Long:
+                                               LOADCONST_L(((constant_long*)
+                                                            (class->cpinfos[i]))->value);
+                                               break;
+                                       case CONSTANT_Float:
+                                               LOADCONST_F(((constant_float*)
+                                                            (class->cpinfos[i]))->value);
+                                               break;
+                                       case CONSTANT_Double:
+                                               LOADCONST_D(((constant_double*)
+                                                            (class->cpinfos[i]))->value);
+                                               break;
+                                       case CONSTANT_String:
+                                               LOADCONST_A(literalstring_new((unicode*)
+                                                                             (class->cpinfos[i])));
+                                               break;
+                                       default: panic("Invalid constant type to push");
+                                       }
+                               break;
+
+                       case JAVA_ACONST_NULL:
+                               LOADCONST_A(NULL);
+                               break;
+
+                       case JAVA_ICONST_M1:
+                       case JAVA_ICONST_0:
+                       case JAVA_ICONST_1:
+                       case JAVA_ICONST_2:
+                       case JAVA_ICONST_3:
+                       case JAVA_ICONST_4:
+                       case JAVA_ICONST_5:
+                               LOADCONST_I(opcode - JAVA_ICONST_0);
+                               break;
+
+                       case JAVA_LCONST_0:
+                       case JAVA_LCONST_1:
+                               LOADCONST_L(opcode - JAVA_LCONST_0);
+                               break;
+
+                       case JAVA_FCONST_0:
+                       case JAVA_FCONST_1:
+                       case JAVA_FCONST_2:
+                               LOADCONST_F(opcode - JAVA_FCONST_0);
+                               break;
+
+                       case JAVA_DCONST_0:
+                       case JAVA_DCONST_1:
+                               LOADCONST_D(opcode - JAVA_DCONST_0);
+                               break;
+
+                       /* loading variables onto the stack */
+
+                       case JAVA_ILOAD:
+                       case JAVA_LLOAD:
+                       case JAVA_FLOAD:
+                       case JAVA_DLOAD:
+                       case JAVA_ALOAD:
+                               if (!iswide)
+                                       i = code_get_u1(p+1);
+                               else {
+                                       i = code_get_u2(p+1);
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               OP1(opcode, i);
+                               break;
+
+                       case JAVA_ILOAD_0:
+                       case JAVA_ILOAD_1:
+                       case JAVA_ILOAD_2:
+                       case JAVA_ILOAD_3:
+                               OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
+                               break;
+
+                       case JAVA_LLOAD_0:
+                       case JAVA_LLOAD_1:
+                       case JAVA_LLOAD_2:
+                       case JAVA_LLOAD_3:
+                               OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
+                               break;
+
+                       case JAVA_FLOAD_0:
+                       case JAVA_FLOAD_1:
+                       case JAVA_FLOAD_2:
+                       case JAVA_FLOAD_3:
+                               OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
+                               break;
+
+                       case JAVA_DLOAD_0:
+                       case JAVA_DLOAD_1:
+                       case JAVA_DLOAD_2:
+                       case JAVA_DLOAD_3:
+                               OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
+                               break;
+
+                       case JAVA_ALOAD_0:
+                       case JAVA_ALOAD_1:
+                       case JAVA_ALOAD_2:
+                       case JAVA_ALOAD_3:
+                               OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
+                               break;
+
+                       /* storing stack values into local variables */
+
+                       case JAVA_ISTORE:
+                       case JAVA_LSTORE:
+                       case JAVA_FSTORE:
+                       case JAVA_DSTORE:
+                       case JAVA_ASTORE:
+                               if (!iswide)
+                                       i = code_get_u1(p+1);
+                               else {
+                                       i = code_get_u2(p+1);
+                                       iswide=false;
+                                       nextp = p+3;
+                                       }
+                               OP1(opcode, i);
+                               break;
+
+                       case JAVA_ISTORE_0:
+                       case JAVA_ISTORE_1:
+                       case JAVA_ISTORE_2:
+                       case JAVA_ISTORE_3:
+                               OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
+                               break;
+
+                       case JAVA_LSTORE_0:
+                       case JAVA_LSTORE_1:
+                       case JAVA_LSTORE_2:
+                       case JAVA_LSTORE_3:
+                               OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
+                               break;
+
+                       case JAVA_FSTORE_0:
+                       case JAVA_FSTORE_1:
+                       case JAVA_FSTORE_2:
+                       case JAVA_FSTORE_3:
+                               OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
+                               break;
+
+                       case JAVA_DSTORE_0:
+                       case JAVA_DSTORE_1:
+                       case JAVA_DSTORE_2:
+                       case JAVA_DSTORE_3:
+                               OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
+                               break;
+
+                       case JAVA_ASTORE_0:
+                       case JAVA_ASTORE_1:
+                       case JAVA_ASTORE_2:
+                       case JAVA_ASTORE_3:
+                               OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
+                               break;
+
+                       case JAVA_IINC:
+                               {
+                               int v;
+                               
+                               if (!iswide) {
+                                       i = code_get_u1(p + 1);
+                                       v = code_get_s1(p + 2);
+                                       }
+                               else {
+                                       i = code_get_u2(p + 1);
+                                       v = code_get_s2(p + 3);
+                                       iswide = false;
+                                       nextp = p+5;
+                                       }
+                               OP2I(opcode, i, v);
+                               }
+                               break;
+
+                       /* wider index for loading, storing and incrementing */
+
+                       case JAVA_WIDE:
+                               iswide = true;
+                               nextp = p + 1;
+                               break;
+
+                       /*********************** managing arrays **************************/
+
+                       case JAVA_NEWARRAY:
+                               OP2I(ICMD_CHECKASIZE, 0, 0);
+                               switch (code_get_s1(p+1)) {
+                                       case 4:
+                                               BUILTIN1((functionptr)builtin_newarray_boolean, TYPE_ADR);
+                                               break;
+                                       case 5:
+                                               BUILTIN1((functionptr)builtin_newarray_char, TYPE_ADR);
+                                               break;
+                                       case 6:
+                                               BUILTIN1((functionptr)builtin_newarray_float, TYPE_ADR);
+                                               break;
+                                       case 7:
+                                               BUILTIN1((functionptr)builtin_newarray_double, TYPE_ADR);
+                                               break;
+                                       case 8:
+                                               BUILTIN1((functionptr)builtin_newarray_byte, TYPE_ADR);
+                                               break;
+                                       case 9:
+                                               BUILTIN1((functionptr)builtin_newarray_short, TYPE_ADR);
+                                               break;
+                                       case 10:
+                                               BUILTIN1((functionptr)builtin_newarray_int, TYPE_ADR);
+                                               break;
+                                       case 11:
+                                               BUILTIN1((functionptr)builtin_newarray_long, TYPE_ADR);
+                                               break;
+                                       default: panic("Invalid array-type to create");
+                                       }
+                               break;
+
+                       case JAVA_ANEWARRAY:
+                               OP2I(ICMD_CHECKASIZE, 0, 0);
+                               i = code_get_u2(p+1);
+                               /* array or class type ? */
+                               if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+                                       LOADCONST_A(class_getconstant(class, i,
+                                                                     CONSTANT_Arraydescriptor));
+                                       BUILTIN2((functionptr)builtin_newarray_array, TYPE_ADR);
+                                       }
+                               else {
+                                       LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+                                       BUILTIN2((functionptr)builtin_anewarray, TYPE_ADR);
+                                       }
+                               break;
+
+                       case JAVA_MULTIANEWARRAY:
+                               isleafmethod=false;
+                               i = code_get_u2(p+1);
+                               {
+                               int v = code_get_u1(p+3);
+                               constant_arraydescriptor *desc =
+                                   class_getconstant (class, i, CONSTANT_Arraydescriptor);
+                               OP2A(opcode, v, desc);
+                               }
+                               break;
+
+                       case JAVA_IFEQ:
+                       case JAVA_IFLT:
+                       case JAVA_IFLE:
+                       case JAVA_IFNE:
+                       case JAVA_IFGT:
+                       case JAVA_IFGE:
+                       case JAVA_IFNULL:
+                       case JAVA_IFNONNULL:
+                       case JAVA_IF_ICMPEQ:
+                       case JAVA_IF_ICMPNE:
+                       case JAVA_IF_ICMPLT:
+                       case JAVA_IF_ICMPGT:
+                       case JAVA_IF_ICMPLE:
+                       case JAVA_IF_ICMPGE:
+                       case JAVA_IF_ACMPEQ:
+                       case JAVA_IF_ACMPNE:
+                       case JAVA_GOTO:
+                       case JAVA_JSR:
+                               i = p + code_get_s2(p+1);
+                               bound_check(i);
+                               block_insert(i);
+                               blockend = true;
+                               OP1(opcode, i);
+                               break;
+                       case JAVA_GOTO_W:
+                       case JAVA_JSR_W:
+                               i = p + code_get_s4(p+1);
+                               bound_check(i);
+                               block_insert(i);
+                               blockend = true;
+                               OP1(opcode, i);
+                               break;
+
+                       case JAVA_RET:
+                               if (!iswide)
+                                       i = code_get_u1(p+1);
+                               else {
+                                       i = code_get_u2(p+1);
+                                       nextp = p+3;
+                                       iswide = false;
+                                       }
+                               blockend = true;
+                               OP1(opcode, i);
+                               break;
+
+                       case JAVA_IRETURN:
+                       case JAVA_LRETURN:
+                       case JAVA_FRETURN:
+                       case JAVA_DRETURN:
+                       case JAVA_ARETURN:
+                       case JAVA_RETURN:
+                               blockend = true;
+                               OP(opcode);
+                               break;
+
+                       case JAVA_ATHROW:
+                               blockend = true;
+                               OP(opcode);
+                               break;
+                               
+
+                       /**************** table jumps *****************/
+
+                       case JAVA_LOOKUPSWITCH:
+                               {
+                               s4 num, j;
+
+                               blockend = true;
+                               nextp = ALIGN((p + 1), 4);
+                               OP2A(opcode, 0, jcode + nextp);
+
+                               /* default target */
+
+                               j =  p + code_get_s4(nextp);
+                               *((s4*)(jcode + nextp)) = j;     /* restore for little endian */
+                               nextp += 4;
+                               bound_check(j);
+                               block_insert(j);
+
+                               /* number of pairs */
+
+                               num = code_get_u4(nextp);
+                               *((s4*)(jcode + nextp)) = num;
+                               nextp += 4;
+
+                               for (i = 0; i < num; i++) {
+
+                                       /* value */
+
+                                       j = code_get_s4(nextp);
+                                       *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+                                       nextp += 4;
+
+                                       /* target */
+
+                                       j = p + code_get_s4(nextp);
+                                       *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+                                       nextp += 4;
+                                       bound_check(j);
+                                       block_insert(j);
+                                       }
+
+                               break;
+                               }
+
+
+                       case JAVA_TABLESWITCH:
+                               {
+                               s4 num, j;
+
+                               blockend = true;
+                               nextp = ALIGN((p + 1), 4);
+                               OP2A(opcode, 0, jcode + nextp);
+
+                               /* default target */
+
+                               j = p + code_get_s4(nextp);
+                               *((s4*)(jcode + nextp)) = j;     /* restore for little endian */
+                               nextp += 4;
+                               bound_check(j);
+                               block_insert(j);
+
+                               /* lower bound */
+
+                               j = code_get_s4(nextp);
+                               *((s4*)(jcode + nextp)) = j;     /* restore for little endian */
+                               nextp += 4;
+
+                               /* upper bound */
+
+                               num = code_get_s4(nextp);
+                               *((s4*)(jcode + nextp)) = num;   /* restore for little endian */
+                               nextp += 4;
+
+                               num -= j;
+
+                               for (i = 0; i <= num; i++) {
+                                       j = p + code_get_s4(nextp);
+                                       *((s4*)(jcode + nextp)) = j; /* restore for little endian */
+                                       nextp += 4;
+                                       bound_check(j);
+                                       block_insert(j);
+                                       }
+
+                               break;
+                               }
+
+
+                       /************ load and store of object fields ********/
+
+                       case JAVA_AASTORE:
+                               BUILTIN3((functionptr) new_builtin_aastore, TYPE_VOID);
+                               break;
+
+                       case JAVA_PUTSTATIC:
+                       case JAVA_GETSTATIC:
+                               i = code_get_u2(p + 1);
+                               {
+                               constant_FMIref *fr;
+                               fieldinfo *fi;
+                               fr = class_getconstant (class, i, CONSTANT_Fieldref);
+                               fi = class_findfield (fr->class, fr->name, fr->descriptor);
+                               compiler_addinitclass (fr->class);
+                               OP2A(opcode, fi->type, &(fi->value));
+                               }
+                               break;
+                       case JAVA_PUTFIELD:
+                       case JAVA_GETFIELD:
+                               i = code_get_u2(p + 1);
+                               {
+                               constant_FMIref *fr;
+                               fieldinfo *fi;
+                               fr = class_getconstant (class, i, CONSTANT_Fieldref);
+                               fi = class_findfield (fr->class, fr->name, fr->descriptor);
+                               OP2I(opcode, fi->type, fi->offset);
+                               }
+                               break;
+
+
+                       /*** method invocation ***/
+
+                       case JAVA_INVOKESTATIC:
+                               i = code_get_u2(p + 1);
+                               {
+                               constant_FMIref *mr;
+                               methodinfo *mi;
+                               
+                               mr = class_getconstant (class, i, CONSTANT_Methodref);
+                               mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+                               if (! (mi->flags & ACC_STATIC))
+                                       panic ("Static/Nonstatic mismatch calling static method");
+                               descriptor2types(mi);
+                               isleafmethod=false;
+                               OP2A(opcode, mi->paramcount, mi);
+                               }
+                               break;
+                       case JAVA_INVOKESPECIAL:
+                       case JAVA_INVOKEVIRTUAL:
+                               i = code_get_u2(p + 1);
+                               {
+                               constant_FMIref *mr;
+                               methodinfo *mi;
+                               
+                               mr = class_getconstant (class, i, CONSTANT_Methodref);
+                               mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+                               if (mi->flags & ACC_STATIC)
+                                       panic ("Static/Nonstatic mismatch calling static method");
+                               descriptor2types(mi);
+                               isleafmethod=false;
+                               OP2A(opcode, mi->paramcount, mi);
+                               }
+                               break;
+                       case JAVA_INVOKEINTERFACE:
+                               i = code_get_u2(p + 1);
+                               {
+                               constant_FMIref *mr;
+                               methodinfo *mi;
+                               
+                               mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
+                               mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+                               if (mi->flags & ACC_STATIC)
+                                       panic ("Static/Nonstatic mismatch calling static method");
+                               descriptor2types(mi);
+                               isleafmethod=false;
+                               OP2A(opcode, mi->paramcount, mi);
+                               }
+                               break;
+
+                       /***** miscellaneous object operations ****/
+
+                       case JAVA_NEW:
+                               i = code_get_u2 (p+1);
+                               LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+                               BUILTIN1((functionptr) builtin_new, TYPE_ADR);
+                               break;
+
+                       case JAVA_CHECKCAST:
+                               i = code_get_u2(p+1);
+
+                               /* array type cast-check */
+                               if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+                                       LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
+                                       BUILTIN2((functionptr) new_builtin_checkarraycast, TYPE_ADR);
+                                       }
+                               else { /* object type cast-check */
+                                       LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+                                       BUILTIN2((functionptr) new_builtin_checkcast, TYPE_ADR);
+                                       }
+                               break;
+
+                       case JAVA_INSTANCEOF:
+                               i = code_get_u2(p+1);
+
+                               /* array type cast-check */
+                               if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
+                                       LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
+                                       BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
+                                       }
+                               else { /* object type cast-check */
+                                       LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+                                       BUILTIN2((functionptr) builtin_instanceof, TYPE_INT);
+                                       }
+                               break;
+
+                       case JAVA_MONITORENTER:
+#ifdef USE_THREADS
+                               if (checksync) {
+#ifdef SOFTNULLPTRCHECK
+                                       if (checknull) {
+                                               BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
+                                               }
+                                       else {
+/*                                             BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID); */
+                                               BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
+                                               }
+#else
+                                       BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID);
+#endif
+                                       }
+                               else
+#endif
+                                       {
+                                       OP(ICMD_NULLCHECKPOP);
+                                       }
+                               break;
+
+                       case JAVA_MONITOREXIT:
+#ifdef USE_THREADS
+                               if (checksync) {
+                                       BUILTIN1((functionptr) builtin_monitorexit, TYPE_VOID);
+                                       }
+                               else
+#endif
+                                       {
+                                       OP(ICMD_POP);
+                                       }
+                               break;
+
+                       /************** any other basic operation **********/
+
+                       case JAVA_IDIV:
+                               if (SUPPORT_DIVISION) {
+                                       OP(opcode);
+                                       }
+                               else {
+                                       BUILTIN2((functionptr) new_builtin_idiv, TYPE_INT);
+                                       }
+                               break;
+
+                       case JAVA_IREM:
+                               if (SUPPORT_DIVISION) {
+                                       OP(opcode);
+                                       }
+                               else {
+                                       BUILTIN2((functionptr) new_builtin_irem, TYPE_INT);
+                                       }
+                               break;
+
+                       case JAVA_LDIV:
+                               if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+                                       OP(opcode);
+                                       }
+                               else {
+                                       BUILTIN2((functionptr) new_builtin_ldiv, TYPE_LONG);
+                                       }
+                               break;
+
+                       case JAVA_LREM:
+                               if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
+                                       OP(opcode);
+                                       }
+                               else {
+                                       BUILTIN2((functionptr) new_builtin_lrem, TYPE_LONG);
+                                       }
+                               break;
+
+                       case JAVA_FREM:
+                               BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
+                               break;
+
+                       case JAVA_DREM:
+                               BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
+                               break;
+
+                       case JAVA_F2I:
+                               if (checkfloats) {
+                                       BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
+                                       }
+                               else {
+                                       OP(opcode);
+                                       }
+                               break;
+
+                       case JAVA_F2L:
+                               if (checkfloats) {
+                                       BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
+                                       }
+                               else {
+                                       OP(opcode);
+                                       }
+                               break;
+
+                       case JAVA_D2I:
+                               if (checkfloats) {
+                                       BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
+                                       }
+                               else {
+                                       OP(opcode);
+                                       }
+                               break;
+
+                       case JAVA_D2L:
+                               if (checkfloats) {
+                                       BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
+                                       }
+                               else {
+                                       OP(opcode);
+                                       }
+                               break;
+
+                       case JAVA_BREAKPOINT:
+                               panic("Illegal opcode Breakpoint encountered");
+                               break;
+
+                       case 203:
+                       case 204:
+                       case 205:
+                       case 206:
+                       case 207:
+                       case 208:
+                       case 209:
+                       case 210:
+                       case 211:
+                       case 212:
+                       case 213:
+                       case 214:
+                       case 215:
+                       case 216:
+                       case 217:
+                       case 218:
+                       case 219:
+                       case 220:
+                       case 221:
+                       case 222:
+                       case 223:
+                       case 224:
+                       case 225:
+                       case 226:
+                       case 227:
+                       case 228:
+                       case 229:
+                       case 230:
+                       case 231:
+                       case 232:
+                       case 233:
+                       case 234:
+                       case 235:
+                       case 236:
+                       case 237:
+                       case 238:
+                       case 239:
+                       case 240:
+                       case 241:
+                       case 242:
+                       case 243:
+                       case 244:
+                       case 245:
+                       case 246:
+                       case 247:
+                       case 248:
+                       case 249:
+                       case 250:
+                       case 251:
+                       case 252:
+                       case 253:
+                       case 254:
+                       case 255:
+                               printf("Illegal opcode %d at instr %d", opcode, ipc);
+                               panic("encountered");
+                               break;
+
+                       default:
+                               OP(opcode);
+                               break;
+
+                       } /* end switch */
+
+               } /* end for */
+
+       if (p != jcodelength)
+               panic("Command-sequence crosses code-boundary");
+
+       if (!blockend)
+               panic("Code does not end with branch/return/athrow - stmt");    
+
+       /* adjust block count if target 0 is not first intermediate instruction   */
+
+       if (!block_index[0] || (block_index[0] > 1))
+               b_count++;
+
+       /* copy local to global variables   */
+
+       instr_count = ipc;
+       block_count = b_count;
+       stack_count = s_count + block_count * maxstack;
+
+       /* allocate stack table */
+
+       stack = DMNEW(stackelement, stack_count);
+
+       {
+       basicblock  *bptr;
+
+       bptr = block = DMNEW(basicblock, b_count + 1);    /* one more for end ipc */
+
+       b_count = 0;
+       
+       /* additional block if target 0 is not first intermediate instruction     */
+
+       if (!block_index[0] || (block_index[0] > 1)) {
+               bptr->ipc = 0;
+               bptr->mpc = -1;
+               bptr->flags = -1;
+               bptr->type = BBTYPE_STD;
+               bptr->branchrefs = NULL;
+               bptr++;
+               b_count++;
+               }
+
+       /* allocate blocks */
+
+       for (p = 0; p < jcodelength; p++)
+               if (block_index[p] & 1) {
+                       bptr->ipc = block_index[p] >> 1;
+                       bptr->mpc = -1;
+                       bptr->flags = -1;
+                       bptr->type = BBTYPE_STD;
+                       bptr->branchrefs = NULL;
+                       block_index[p] = b_count;
+                       bptr++;
+                       b_count++;
+                       }
+
+       /* allocate additional block at end */
+
+       bptr->ipc = instr_count;
+       bptr->mpc = -1;
+       bptr->flags = -1;
+       bptr->type = BBTYPE_STD;
+       bptr->branchrefs = NULL;
+       }
+}
diff --git a/ncomp/nreg.c b/ncomp/nreg.c
new file mode 100644 (file)
index 0000000..6b8bfc5
--- /dev/null
@@ -0,0 +1,976 @@
+/******************************* comp/reg.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       The register-manager.
+
+       Authors:  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                 Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/23
+
+*******************************************************************************/
+
+static varinfo5 *locals;
+static varinfo5 *interfaces;
+
+static int intregsnum;              /* absolute number of integer registers   */
+static int floatregsnum;            /* absolute number of float registers     */ 
+
+static int intreg_ret;              /* register to return integer values      */
+static int intreg_argnum;           /* number of integer argument registers   */
+
+static int floatreg_ret;            /* register for return float values       */
+static int fltreg_argnum;           /* number of float argument registers     */
+
+
+static int *argintregs;             /* scratch integer registers              */
+static int *tmpintregs = NULL;      /* scratch integer registers              */
+static int *savintregs;             /* saved integer registers                */
+static int *argfltregs;             /* scratch float registers                */
+static int *tmpfltregs;             /* scratch float registers                */
+static int *savfltregs;             /* saved float registers                  */
+static int *freetmpintregs;         /* free scratch integer registers         */
+static int *freesavintregs;         /* free saved integer registers           */
+static int *freetmpfltregs;         /* free scratch float registers           */
+static int *freesavfltregs;         /* free saved float registers             */
+
+static int *freemem;                /* free scratch memory                    */
+static int memuse;                  /* used memory count                      */
+static int ifmemuse;                /* interface used memory count            */
+static int maxmemuse;               /* maximal used memory count (spills)     */
+static int freememtop;              /* free memory count                      */
+
+static int tmpintregcnt;            /* scratch integer register count         */
+static int savintregcnt;            /* saved integer register count           */
+static int tmpfltregcnt;            /* scratch float register count           */
+static int savfltregcnt;            /* saved float register count             */
+
+static int iftmpintregcnt;          /* iface scratch integer register count   */
+static int ifsavintregcnt;          /* iface saved integer register count     */
+static int iftmpfltregcnt;          /* iface scratch float register count     */
+static int ifsavfltregcnt;          /* iface saved float register count       */
+
+static int tmpintreguse;            /* used scratch integer register count    */
+static int savintreguse;            /* used saved integer register count      */
+static int tmpfltreguse;            /* used scratch float register count      */
+static int savfltreguse;            /* used saved float register count        */
+
+static int maxtmpintreguse;         /* max used scratch int register count    */
+static int maxsavintreguse;         /* max used saved int register count      */
+static int maxtmpfltreguse;         /* max used scratch float register count  */
+static int maxsavfltreguse;         /* max used saved float register count    */
+
+static int freetmpinttop;           /* free scratch integer register count    */
+static int freesavinttop;           /* free saved integer register count      */
+static int freetmpflttop;           /* free scratch float register count      */
+static int freesavflttop;           /* free saved float register count        */
+
+static int savedregs_num;              /* total number of registers to be saved      */
+static int arguments_num;       /* size of parameter field in the stackframe  */
+
+
+
+/****************** function reg_init ******************************************
+
+       initialises the register-allocator
+       
+*******************************************************************************/
+
+static void reg_init()
+{
+       int n;
+       
+       if (!tmpintregs) {
+
+               if (TYPE_INT != 0 || TYPE_ADR != 4) 
+                       panic ("JAVA-Basictypes have been changed");
+
+               intreg_argnum = 0;
+               tmpintregcnt = 0;
+               savintregcnt = 0;
+
+               for (intregsnum = 0; nregdescint[intregsnum] != REG_END; intregsnum++) {
+                       switch (nregdescint[intregsnum]) {
+                               case REG_SAV: savintregcnt++;
+                                             break;
+                               case REG_TMP: tmpintregcnt++;
+                                             break;
+                               case REG_ARG: intreg_argnum++;
+                               }
+                       }
+
+               argintregs = MNEW (int, intreg_argnum);
+               tmpintregs = MNEW (int, tmpintregcnt);
+               savintregs = MNEW (int, savintregcnt);
+               freetmpintregs = MNEW (int, tmpintregcnt);
+               freesavintregs = MNEW (int, savintregcnt);
+
+               intreg_argnum = 0;
+               tmpintreguse = 0;
+               savintreguse = 0;
+
+               for (n = 0; n < intregsnum; n++) {
+                       switch (nregdescint[n]) {
+                               case REG_RET: intreg_ret = n; 
+                                             break;
+                               case REG_SAV: savintregs[savintreguse++] = n;
+                                             break;
+                               case REG_TMP: tmpintregs[tmpintreguse++] = n;
+                                             break;
+                               case REG_ARG: argintregs[intreg_argnum++] = n;
+                                             break;
+                               }
+                       }
+                                       
+               
+               fltreg_argnum = 0;
+               tmpfltregcnt = 0;
+               savfltregcnt = 0;
+
+               for (floatregsnum = 0; nregdescfloat[floatregsnum] != REG_END; floatregsnum++) {
+                       switch (nregdescfloat[floatregsnum]) {
+                               case REG_SAV: savfltregcnt++;
+                                             break;
+                               case REG_TMP: tmpfltregcnt++;
+                                             break;
+                               case REG_ARG: fltreg_argnum++;
+                                             break;
+                               }
+                       }
+
+               argfltregs = MNEW (int, fltreg_argnum);
+               tmpfltregs = MNEW (int, tmpfltregcnt);
+               savfltregs = MNEW (int, savfltregcnt);
+               freetmpfltregs = MNEW (int, tmpfltregcnt);
+               freesavfltregs = MNEW (int, savfltregcnt);
+
+               fltreg_argnum = 0;
+               tmpfltreguse = 0;
+               savfltreguse = 0;
+
+               for (n = 0; n < floatregsnum; n++) {
+                       switch (nregdescfloat[n]) {
+                               case REG_RET: floatreg_ret = n; 
+                                             break;
+                               case REG_SAV: savfltregs[savfltreguse++] = n;
+                                             break;
+                               case REG_TMP: tmpfltregs[tmpfltreguse++] = n;
+                                             break;
+                               case REG_ARG: argfltregs[fltreg_argnum++] = n;
+                                             break;
+                               }
+                       }
+                                       
+               }
+
+}
+
+
+/********************** function reg_close *************************************
+
+       releases all allocated space for registers
+
+*******************************************************************************/
+
+static void reg_close ()
+{
+       if (argintregs) MFREE (argintregs, int, intreg_argnum);
+       if (argfltregs) MFREE (argfltregs, int, fltreg_argnum);
+       if (tmpintregs) MFREE (tmpintregs, int, tmpintregcnt);
+       if (savintregs) MFREE (savintregs, int, savintregcnt);
+       if (tmpfltregs) MFREE (tmpfltregs, int, tmpfltregcnt);
+       if (savfltregs) MFREE (savfltregs, int, savfltregcnt);
+
+       if (freetmpintregs) MFREE (freetmpintregs, int, tmpintregcnt);
+       if (freesavintregs) MFREE (freesavintregs, int, savintregcnt);
+       if (freetmpfltregs) MFREE (freetmpfltregs, int, tmpfltregcnt);
+       if (freesavfltregs) MFREE (freesavfltregs, int, savfltregcnt);
+}
+
+
+/****************** function local_init ****************************************
+
+       initialises the local variable and interfaces table
+       
+*******************************************************************************/
+
+static void local_init()
+{
+       int i;
+       varinfo5 *v;
+
+       freemem    = DMNEW(int, maxstack);
+       locals     = DMNEW(varinfo5, maxlocals);
+       interfaces = DMNEW(varinfo5, maxstack);
+
+       for (v = locals, i = maxlocals; i > 0; v++, i--) {
+               v[0][TYPE_INT].type = -1;
+               v[0][TYPE_LNG].type = -1;
+               v[0][TYPE_FLT].type = -1;
+               v[0][TYPE_DBL].type = -1;
+               v[0][TYPE_ADR].type = -1;
+               }
+
+       for (v = interfaces, i = maxstack; i > 0; v++, i--) {
+               v[0][TYPE_INT].type = -1;
+               v[0][TYPE_INT].flags = 0;
+               v[0][TYPE_LNG].type = -1;
+               v[0][TYPE_LNG].flags = 0;
+               v[0][TYPE_FLT].type = -1;
+               v[0][TYPE_FLT].flags = 0;
+               v[0][TYPE_DBL].type = -1;
+               v[0][TYPE_DBL].flags = 0;
+               v[0][TYPE_ADR].type = -1;
+               v[0][TYPE_ADR].flags = 0;
+               }
+}
+
+
+/************************* function interface_regalloc *****************************
+
+       allocates registers for all interface variables
+       
+*******************************************************************************/
+       
+static void interface_regalloc ()
+{
+       int     s, t, saved;
+       int     intalloc, fltalloc;
+       varinfo *v;
+       
+       /* allocate stack space for passing arguments to called methods */
+
+       if (arguments_num > intreg_argnum)
+               ifmemuse = arguments_num - intreg_argnum;
+       else
+               ifmemuse = 0;
+
+       iftmpintregcnt = tmpintregcnt;
+       ifsavintregcnt = savintregcnt;
+       iftmpfltregcnt = tmpfltregcnt;
+       ifsavfltregcnt = savfltregcnt;
+
+       for (s = 0; s < maxstack; s++) {
+               intalloc = -1; fltalloc = -1;
+               saved = (interfaces[s][TYPE_INT].flags | interfaces[s][TYPE_LNG].flags |
+                        interfaces[s][TYPE_FLT].flags | interfaces[s][TYPE_DBL].flags |
+                        interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
+               for (t = TYPE_INT; t <= TYPE_ADR; t++) {
+                       v = &interfaces[s][t];
+                       if (v->type >= 0) {
+                               if (!saved) {
+                                       if (IS_FLT_DBL_TYPE(t)) {
+                                               if (fltalloc >= 0) {
+                                                       v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
+                                                       v->regoff = interfaces[s][fltalloc].regoff;
+                                                       }
+                                               else if (iftmpfltregcnt > 0) {
+                                                       iftmpfltregcnt--;
+                                                       v->regoff = tmpfltregs[iftmpfltregcnt];
+                                                       }
+                                               else if (ifsavfltregcnt > 0) {
+                                                       ifsavfltregcnt--;
+                                                       v->regoff = savfltregs[ifsavfltregcnt];
+                                                       }
+                                               else {
+                                                       v->flags |= INMEMORY;
+                                                       v->regoff = ifmemuse++;
+                                                       }
+                                               fltalloc = t;
+                                               }
+                                       else {
+                                               if (intalloc >= 0) {
+                                                       v->flags |= interfaces[s][intalloc].flags & INMEMORY;
+                                                       v->regoff = interfaces[s][intalloc].regoff;
+                                                       }
+                                               else if (iftmpintregcnt > 0) {
+                                                       iftmpintregcnt--;
+                                                       v->regoff = tmpintregs[iftmpintregcnt];
+                                                       }
+                                               else if (ifsavintregcnt > 0) {
+                                                       ifsavintregcnt--;
+                                                       v->regoff = savintregs[ifsavintregcnt];
+                                                       }
+                                               else {
+                                                       v->flags |= INMEMORY;
+                                                       v->regoff = ifmemuse++;
+                                                       }
+                                               intalloc = t;
+                                               }
+                                       }
+                               else {
+                                       if (IS_FLT_DBL_TYPE(t)) {
+                                               if (fltalloc >= 0) {
+                                                       v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
+                                                       v->regoff = interfaces[s][fltalloc].regoff;
+                                                       }
+                                               else if (ifsavfltregcnt > 0) {
+                                                       ifsavfltregcnt--;
+                                                       v->regoff = savfltregs[ifsavfltregcnt];
+                                                       }
+                                               else {
+                                                       v->flags |= INMEMORY;
+                                                       v->regoff = ifmemuse++;
+                                                       }
+                                               fltalloc = t;
+                                               }
+                                       else {
+                                               if (intalloc >= 0) {
+                                                       v->flags |= interfaces[s][intalloc].flags & INMEMORY;
+                                                       v->regoff = interfaces[s][intalloc].regoff;
+                                                       }
+                                               else if (ifsavintregcnt > 0) {
+                                                       ifsavintregcnt--;
+                                                       v->regoff = savintregs[ifsavintregcnt];
+                                                       }
+                                               else {
+                                                       v->flags |= INMEMORY;
+                                                       v->regoff = ifmemuse++;
+                                                       }
+                                               intalloc = t;
+                                               }
+                                       }
+                               } /* if (type >= 0) */
+                       }     /* for t */
+               }         /* for s */
+       maxmemuse = ifmemuse;
+       maxtmpintreguse = iftmpintregcnt;
+       maxsavintreguse = ifsavintregcnt;
+       maxtmpfltreguse = iftmpfltregcnt;
+       maxsavfltreguse = ifsavfltregcnt;
+}
+
+
+/************************* function local_regalloc *****************************
+
+       allocates registers for all local variables
+       
+*******************************************************************************/
+       
+static void local_regalloc ()
+{
+       int     s, t;
+       int     intalloc, fltalloc;
+       varinfo *v;
+       
+       if (isleafmethod) {
+               for (s = 0; s < maxlocals; s++) {
+                       intalloc = -1; fltalloc = -1;
+                       for (t = TYPE_INT; t <= TYPE_ADR; t++) {
+                               v = &locals[s][t];
+                               if (v->type >= 0) {
+                                       if (IS_FLT_DBL_TYPE(t)) {
+                                               if (fltalloc >= 0) {
+                                                       v->flags = locals[s][fltalloc].flags;
+                                                       v->regoff = locals[s][fltalloc].regoff;
+                                                       }
+                                               else if (s < fltreg_argnum) {
+                                                       v->flags = 0;
+                                                       v->regoff = argfltregs[s];
+                                                       }
+                                               else if (maxtmpfltreguse > 0) {
+                                                       maxtmpfltreguse--;
+                                                       v->flags = 0;
+                                                       v->regoff = tmpfltregs[maxtmpfltreguse];
+                                                       }
+                                               else if (maxsavfltreguse > 0) {
+                                                       maxsavfltreguse--;
+                                                       v->flags = 0;
+                                                       v->regoff = savfltregs[maxsavfltreguse];
+                                                       }
+                                               else {
+                                                       v->flags = INMEMORY;
+                                                       v->regoff = maxmemuse++;
+                                                       }
+                                               fltalloc = t;
+                                               }
+                                       else {
+                                               if (intalloc >= 0) {
+                                                       v->flags = locals[s][intalloc].flags;
+                                                       v->regoff = locals[s][intalloc].regoff;
+                                                       }
+                                               else if (s < intreg_argnum) {
+                                                       v->flags = 0;
+                                                       v->regoff = argintregs[s];
+                                                       }
+                                               else if (maxtmpintreguse > 0) {
+                                                       maxtmpintreguse--;
+                                                       v->flags = 0;
+                                                       v->regoff = tmpintregs[maxtmpintreguse];
+                                                       }
+                                               else if (maxsavintreguse > 0) {
+                                                       maxsavintreguse--;
+                                                       v->flags = 0;
+                                                       v->regoff = savintregs[maxsavintreguse];
+                                                       }
+                                               else {
+                                                       v->flags = INMEMORY;
+                                                       v->regoff = maxmemuse++;
+                                                       }
+                                               intalloc = t;
+                                               }
+                                       }
+                               }
+                       }
+               return;
+               }
+       for (s = 0; s < maxlocals; s++) {
+               intalloc = -1; fltalloc = -1;
+               for (t=TYPE_INT; t<=TYPE_ADR; t++) {
+                       v = &locals[s][t];
+                       if (v->type >= 0) {
+                               if (IS_FLT_DBL_TYPE(t)) {
+                                       if (fltalloc >= 0) {
+                                               v->flags = locals[s][fltalloc].flags;
+                                               v->regoff = locals[s][fltalloc].regoff;
+                                               }
+                                       else if (maxsavfltreguse > 0) {
+                                               maxsavfltreguse--;
+                                               v->flags = 0;
+                                               v->regoff = savfltregs[maxsavfltreguse];
+                                               }
+                                       else {
+                                               v->flags = INMEMORY;
+                                               v->regoff = maxmemuse++;
+                                               }
+                                       fltalloc = t;
+                                       }
+                               else {
+                                       if (intalloc >= 0) {
+                                               v->flags = locals[s][intalloc].flags;
+                                               v->regoff = locals[s][intalloc].regoff;
+                                               }
+                                       else if (maxsavintreguse > 0) {
+                                               maxsavintreguse--;
+                                               v->flags = 0;
+                                               v->regoff = savintregs[maxsavintreguse];
+                                               }
+                                       else {
+                                               v->flags = INMEMORY;
+                                               v->regoff = maxmemuse++;
+                                               }
+                                       intalloc = t;
+                                       }
+                               }
+                       }
+               }
+}
+
+
+static void reg_init_temp()
+{
+       freememtop = 0;
+       memuse = ifmemuse;
+
+       freetmpinttop = 0;
+       freesavinttop = 0;
+       freetmpflttop = 0;
+       freesavflttop = 0;
+       tmpintreguse = iftmpintregcnt;
+       savintreguse = ifsavintregcnt;
+       tmpfltreguse = iftmpfltregcnt;
+       savfltreguse = ifsavfltregcnt;
+}
+
+
+#define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
+
+static void reg_new_temp_func(stackptr s)
+{
+if (s->flags & SAVEDVAR) {
+       if (IS_FLT_DBL_TYPE(s->type)) {
+               if (freesavflttop > 0) {
+                       freesavflttop--;
+                       s->regoff = freesavfltregs[freesavflttop];
+                       return;
+                       }
+               else if (savfltreguse > 0) {
+                       savfltreguse--;
+                       if (savfltreguse < maxsavfltreguse)
+                               maxsavfltreguse = savfltreguse;
+                       s->regoff = savfltregs[savfltreguse];
+                       return;
+                       }
+               }
+       else {
+               if (freesavinttop > 0) {
+                       freesavinttop--;
+                       s->regoff = freesavintregs[freesavinttop];
+                       return;
+                       }
+               else if (savintreguse > 0) {
+                       savintreguse--;
+                       if (savintreguse < maxsavintreguse)
+                               maxsavintreguse = savintreguse;
+                       s->regoff = savintregs[savintreguse];
+                       return;
+                       }
+               }
+       }
+else {
+       if (IS_FLT_DBL_TYPE(s->type)) {
+               if (freetmpflttop > 0) {
+                       freetmpflttop--;
+                       s->regoff = freetmpfltregs[freetmpflttop];
+                       return;
+                       }
+               else if (tmpfltreguse > 0) {
+                       tmpfltreguse--;
+                       if (tmpfltreguse < maxtmpfltreguse)
+                               maxtmpfltreguse = tmpfltreguse;
+                       s->regoff = tmpfltregs[tmpfltreguse];
+                       return;
+                       }
+               }
+       else {
+               if (freetmpinttop > 0) {
+                       freetmpinttop--;
+                       s->regoff = freetmpintregs[freetmpinttop];
+                       return;
+                       }
+               else if (tmpintreguse > 0) {
+                       tmpintreguse--;
+                       if (tmpintreguse < maxtmpintreguse)
+                               maxtmpintreguse = tmpintreguse;
+                       s->regoff = tmpintregs[tmpintreguse];
+                       return;
+                       }
+               }
+       }
+if (freememtop > 0) {
+       freememtop--;
+       s->regoff = freemem[freememtop];
+       }
+else {
+       s->regoff = memuse++;
+       if (memuse > maxmemuse)
+               maxmemuse = memuse;
+       }
+s->flags |= INMEMORY;
+}
+
+
+#define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
+
+static void reg_free_temp_func(stackptr s)
+{
+if (s->flags & INMEMORY)
+       freemem[freememtop++] = s->regoff;
+else if (IS_FLT_DBL_TYPE(s->type)) {
+       if (s->flags & SAVEDVAR)
+               freesavfltregs[freesavflttop++] = s->regoff;
+       else
+               freetmpfltregs[freetmpflttop++] = s->regoff;
+       }
+else
+       if (s->flags & SAVEDVAR)
+               freesavintregs[freesavinttop++] = s->regoff;
+       else
+               freetmpintregs[freetmpinttop++] = s->regoff;
+}
+
+
+static void allocate_scratch_registers()
+{
+       int b_count;
+       int opcode, i, len;
+       stackptr    src, dst;
+       instruction *iptr = instr;
+       basicblock  *bptr;
+       
+       b_count = block_count;
+       bptr = block;
+       while (--b_count >= 0) {
+               if (bptr->flags >= BBREACHED) {
+                       dst = bptr->instack;
+                       reg_init_temp();
+                       i = bptr[0].ipc;
+                       len = bptr[1].ipc - i;
+                       iptr = &instr[i];
+                       while (--len >= 0)  {
+                               src = dst;
+                               dst = iptr->dst;
+                               opcode = iptr->opc;
+                               switch (opcode) {
+
+                                       /* pop 0 push 0 */
+
+                                       case ICMD_NOP:
+                                       case ICMD_CHECKASIZE:
+                                       case ICMD_IINC:
+                                       case ICMD_JSR:
+                                       case ICMD_RET:
+                                       case ICMD_RETURN:
+                                       case ICMD_GOTO:
+                                               break;
+
+                                       /* pop 0 push 1 const */
+                                       
+                                       case ICMD_ICONST:
+                                       case ICMD_LCONST:
+                                       case ICMD_FCONST:
+                                       case ICMD_DCONST:
+                                       case ICMD_ACONST:
+
+                                       /* pop 0 push 1 load */
+                                       
+                                       case ICMD_ILOAD:
+                                       case ICMD_LLOAD:
+                                       case ICMD_FLOAD:
+                                       case ICMD_DLOAD:
+                                       case ICMD_ALOAD:
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 2 push 1 */
+
+                                       case ICMD_IALOAD:
+                                       case ICMD_LALOAD:
+                                       case ICMD_FALOAD:
+                                       case ICMD_DALOAD:
+                                       case ICMD_AALOAD:
+
+                                       case ICMD_BALOAD:
+                                       case ICMD_CALOAD:
+                                       case ICMD_SALOAD:
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 3 push 0 */
+
+                                       case ICMD_IASTORE:
+                                       case ICMD_LASTORE:
+                                       case ICMD_FASTORE:
+                                       case ICMD_DASTORE:
+                                       case ICMD_AASTORE:
+
+                                       case ICMD_BASTORE:
+                                       case ICMD_CASTORE:
+                                       case ICMD_SASTORE:
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_free_temp(src->prev->prev);
+                                               break;
+
+                                       /* pop 1 push 0 store */
+
+                                       case ICMD_ISTORE:
+                                       case ICMD_LSTORE:
+                                       case ICMD_FSTORE:
+                                       case ICMD_DSTORE:
+                                       case ICMD_ASTORE:
+
+                                       /* pop 1 push 0 */
+
+                                       case ICMD_POP:
+
+                                       case ICMD_IRETURN:
+                                       case ICMD_LRETURN:
+                                       case ICMD_FRETURN:
+                                       case ICMD_DRETURN:
+                                       case ICMD_ARETURN:
+
+                                       case ICMD_ATHROW:
+
+                                       case ICMD_PUTSTATIC:
+
+                                       /* pop 1 push 0 branch */
+
+                                       case ICMD_IFNULL:
+                                       case ICMD_IFNONNULL:
+
+                                       case ICMD_IFEQ:
+                                       case ICMD_IFNE:
+                                       case ICMD_IFLT:
+                                       case ICMD_IFGE:
+                                       case ICMD_IFGT:
+                                       case ICMD_IFLE:
+
+                                       case ICMD_IF_LEQ:
+                                       case ICMD_IF_LNE:
+                                       case ICMD_IF_LLT:
+                                       case ICMD_IF_LGE:
+                                       case ICMD_IF_LGT:
+                                       case ICMD_IF_LLE:
+
+                                       /* pop 1 push 0 table branch */
+
+                                       case ICMD_TABLESWITCH:
+                                       case ICMD_LOOKUPSWITCH:
+
+                                       case ICMD_NULLCHECKPOP:
+                                       case ICMD_MONITORENTER:
+                                       case ICMD_MONITOREXIT:
+                                               reg_free_temp(src);
+                                               break;
+
+                                       /* pop 2 push 0 branch */
+
+                                       case ICMD_IF_ICMPEQ:
+                                       case ICMD_IF_ICMPNE:
+                                       case ICMD_IF_ICMPLT:
+                                       case ICMD_IF_ICMPGE:
+                                       case ICMD_IF_ICMPGT:
+                                       case ICMD_IF_ICMPLE:
+
+                                       case ICMD_IF_LCMPEQ:
+                                       case ICMD_IF_LCMPNE:
+                                       case ICMD_IF_LCMPLT:
+                                       case ICMD_IF_LCMPGE:
+                                       case ICMD_IF_LCMPGT:
+                                       case ICMD_IF_LCMPLE:
+
+                                       case ICMD_IF_ACMPEQ:
+                                       case ICMD_IF_ACMPNE:
+
+                                       /* pop 2 push 0 */
+
+                                       case ICMD_POP2:
+
+                                       case ICMD_PUTFIELD:
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               break;
+
+                                       /* pop 0 push 1 dup */
+                                       
+                                       case ICMD_DUP:
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 0 push 2 dup */
+                                       
+                                       case ICMD_DUP2:
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 2 push 3 dup */
+                                       
+                                       case ICMD_DUP_X1:
+                                               reg_new_temp(dst->prev->prev);
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               break;
+
+                                       /* pop 3 push 4 dup */
+                                       
+                                       case ICMD_DUP_X2:
+                                               reg_new_temp(dst->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev);
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_free_temp(src->prev->prev);
+                                               break;
+
+                                       /* pop 3 push 5 dup */
+                                       
+                                       case ICMD_DUP2_X1:
+                                               reg_new_temp(dst->prev->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev);
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_free_temp(src->prev->prev);
+                                               break;
+
+                                       /* pop 4 push 6 dup */
+                                       
+                                       case ICMD_DUP2_X2:
+                                               reg_new_temp(dst->prev->prev->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev->prev);
+                                               reg_new_temp(dst->prev->prev);
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_free_temp(src->prev->prev);
+                                               reg_free_temp(src->prev->prev->prev);
+                                               break;
+
+                                       /* pop 2 push 2 swap */
+                                       
+                                       case ICMD_SWAP:
+                                               reg_new_temp(dst->prev);
+                                               reg_new_temp(dst);
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               break;
+
+                                       /* pop 2 push 1 */
+                                       
+                                       case ICMD_IADD:
+                                       case ICMD_ISUB:
+                                       case ICMD_IMUL:
+                                       case ICMD_IDIV:
+                                       case ICMD_IREM:
+
+                                       case ICMD_ISHL:
+                                       case ICMD_ISHR:
+                                       case ICMD_IUSHR:
+                                       case ICMD_IAND:
+                                       case ICMD_IOR:
+                                       case ICMD_IXOR:
+
+                                       case ICMD_LADD:
+                                       case ICMD_LSUB:
+                                       case ICMD_LMUL:
+                                       case ICMD_LDIV:
+                                       case ICMD_LREM:
+
+                                       case ICMD_LOR:
+                                       case ICMD_LAND:
+                                       case ICMD_LXOR:
+
+                                       case ICMD_LSHL:
+                                       case ICMD_LSHR:
+                                       case ICMD_LUSHR:
+
+                                       case ICMD_FADD:
+                                       case ICMD_FSUB:
+                                       case ICMD_FMUL:
+                                       case ICMD_FDIV:
+                                       case ICMD_FREM:
+
+                                       case ICMD_DADD:
+                                       case ICMD_DSUB:
+                                       case ICMD_DMUL:
+                                       case ICMD_DDIV:
+                                       case ICMD_DREM:
+
+                                       case ICMD_LCMP:
+                                       case ICMD_FCMPL:
+                                       case ICMD_FCMPG:
+                                       case ICMD_DCMPL:
+                                       case ICMD_DCMPG:
+                                               reg_free_temp(src);
+                                               reg_free_temp(src->prev);
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 1 push 1 */
+                                       
+                                       case ICMD_IADDCONST:
+                                       case ICMD_ISUBCONST:
+                                       case ICMD_IMULCONST:
+                                       case ICMD_IANDCONST:
+                                       case ICMD_IORCONST:
+                                       case ICMD_IXORCONST:
+                                       case ICMD_ISHLCONST:
+                                       case ICMD_ISHRCONST:
+                                       case ICMD_IUSHRCONST:
+
+                                       case ICMD_LADDCONST:
+                                       case ICMD_LSUBCONST:
+                                       case ICMD_LMULCONST:
+                                       case ICMD_LANDCONST:
+                                       case ICMD_LORCONST:
+                                       case ICMD_LXORCONST:
+                                       case ICMD_LSHLCONST:
+                                       case ICMD_LSHRCONST:
+                                       case ICMD_LUSHRCONST:
+
+                                       case ICMD_INEG:
+                                       case ICMD_INT2BYTE:
+                                       case ICMD_INT2CHAR:
+                                       case ICMD_INT2SHORT:
+                                       case ICMD_LNEG:
+                                       case ICMD_FNEG:
+                                       case ICMD_DNEG:
+
+                                       case ICMD_I2L:
+                                       case ICMD_I2F:
+                                       case ICMD_I2D:
+                                       case ICMD_L2I:
+                                       case ICMD_L2F:
+                                       case ICMD_L2D:
+                                       case ICMD_F2I:
+                                       case ICMD_F2L:
+                                       case ICMD_F2D:
+                                       case ICMD_D2I:
+                                       case ICMD_D2L:
+                                       case ICMD_D2F:
+
+                                       case ICMD_CHECKCAST:
+
+                                       case ICMD_ARRAYLENGTH:
+                                       case ICMD_INSTANCEOF:
+
+                                       case ICMD_NEWARRAY:
+                                       case ICMD_ANEWARRAY:
+
+                                       case ICMD_GETFIELD:
+                                               reg_free_temp(src);
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop 0 push 1 */
+                                       
+                                       case ICMD_GETSTATIC:
+
+                                       case ICMD_NEW:
+
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       /* pop many push any */
+                                       
+                                       case ICMD_INVOKEVIRTUAL:
+                                       case ICMD_INVOKESPECIAL:
+                                       case ICMD_INVOKESTATIC:
+                                       case ICMD_INVOKEINTERFACE:
+                                               {
+                                               i = iptr->op1;
+                                               while (--i >= 0) {
+                                                       reg_free_temp(src);
+                                                       src = src->prev;
+                                                       }
+                                               if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
+                                                       reg_new_temp(dst);
+                                               break;
+                                               }
+
+                                       case ICMD_BUILTIN3:
+                                               reg_free_temp(src);
+                                               src = src->prev;
+                                       case ICMD_BUILTIN2:
+                                               reg_free_temp(src);
+                                               src = src->prev;
+                                       case ICMD_BUILTIN1:
+                                               reg_free_temp(src);
+                                               src = src->prev;
+                                               if (iptr->op1 != TYPE_VOID)
+                                                       reg_new_temp(dst);
+                                               break;
+
+                                       case ICMD_MULTIANEWARRAY:
+                                               i = iptr->op1;
+                                               while (--i >= 0) {
+                                                       reg_free_temp(src);
+                                                       src = src->prev;
+                                                       }
+                                               reg_new_temp(dst);
+                                               break;
+
+                                       default:
+                                               printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
+                                               panic("Missing ICMD code during register allocation");
+                                       } /* switch */
+                               iptr++;
+                               } /* while instructions */
+                       } /* if */
+               bptr++;
+       } /* while blocks */
+}
diff --git a/ncomp/nstack.c b/ncomp/nstack.c
new file mode 100644 (file)
index 0000000..eeeeacb
--- /dev/null
@@ -0,0 +1,1498 @@
+/****************************** ncomp/nstack.c *********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Parser for JavaVM to intermediate code translation
+       
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/18
+
+*******************************************************************************/
+
+
+#ifdef STATISTICS
+#define COUNT(cnt) cnt++
+#else
+#define COUNT(cnt)
+#endif
+
+#define STACKRESET {curstack=0;stackdepth=0;}
+
+#define TYPEPANIC  {show_icmd_method();panic("Stack type mismatch");}
+#define CURKIND    curstack->varkind
+#define CURTYPE    curstack->type
+
+#define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0;\
+                        new->varkind=v;new->varnum=n;curstack=new;new++;}
+#define NEWSTACKn(s,n)  NEWSTACK(s,UNDEFVAR,n)
+#define NEWSTACK0(s)    NEWSTACK(s,UNDEFVAR,0)
+#define NEWXSTACK   {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
+
+#define SETDST      {iptr->dst=curstack;}
+#define POP(s)      {if(s!=curstack->type){TYPEPANIC;}\
+                     if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
+                     curstack=curstack->prev;}
+#define POPANY      {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
+                     curstack=curstack->prev;}
+#define COPY(s,d)   {(d)->flags=0;(d)->type=(s)->type;\
+                     (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
+
+#define CONST(s)    {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
+#define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
+#define STORE(s)    {POP(s);SETDST;stackdepth--;}
+#define OP1_0(s)    {POP(s);SETDST;stackdepth--;}
+#define OP1_0ANY    {POPANY;SETDST;stackdepth--;}
+#define OP0_1(s)    {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
+#define OP1_1(s,d)  {POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
+#define OP2_0(s)    {POP(s);POP(s);SETDST;stackdepth-=2;}
+#define OPTT2_0(t,b){POP(t);POP(b);SETDST;stackdepth-=2;}
+#define OP2_1(s)    {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
+#define OP2IAT_1(s) {POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
+                     SETDST;stackdepth--;}
+#define OP2IT_1(s)  {POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
+                     SETDST;stackdepth--;}
+#define OPTT2_1(s,d){POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
+#define OP2_2(s)    {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
+                     NEWSTACKn(s,stackdepth-1);SETDST;}
+#define OP3TIA_0(s) {POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
+#define OP3_0(s)    {POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
+#define POPMANY(i)  {stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
+#define DUP         {NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST;\
+                    stackdepth++;}
+#define SWAP        {COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
+                    new[0].prev=curstack;new[1].prev=new;\
+                    curstack=new+1;new+=2;SETDST;}
+#define DUP_X1      {COPY(curstack,new);COPY(curstack,new+2);POPANY;\
+                    COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
+                    new[1].prev=new;new[2].prev=new+1;\
+                    curstack=new+2;new+=3;SETDST;stackdepth++;}
+#define DUP2_X1     {COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
+                    COPY(curstack,new);COPY(curstack,new+3);POPANY;\
+                    COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
+                    new[1].prev=new;new[2].prev=new+1;\
+                    new[3].prev=new+2;new[4].prev=new+3;\
+                    curstack=new+4;new+=5;SETDST;stackdepth+=2;}
+#define DUP_X2      {COPY(curstack,new);COPY(curstack,new+3);POPANY;\
+                    COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
+                    new[0].prev=curstack;new[1].prev=new;\
+                    new[2].prev=new+1;new[3].prev=new+2;\
+                    curstack=new+3;new+=4;SETDST;stackdepth++;}
+#define DUP2_X2     {COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
+                    COPY(curstack,new);COPY(curstack,new+4);POPANY;\
+                    COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
+                    new[0].prev=curstack;new[1].prev=new;\
+                    new[2].prev=new+1;new[3].prev=new+2;\
+                    new[4].prev=new+3;new[5].prev=new+4;\
+                    curstack=new+5;new+=6;SETDST;stackdepth+=2;}
+
+#define COPYCURSTACK(copy) {\
+       int d;\
+       stackptr s;\
+       if(curstack){\
+               s=curstack;\
+               new+=stackdepth;\
+               d=stackdepth;\
+               copy=new;\
+               while(s){\
+                       copy--;d--;\
+                       copy->prev=copy-1;\
+                       copy->type=s->type;\
+                       copy->flags=0;\
+                       copy->varkind=STACKVAR;\
+                       copy->varnum=d;\
+                       s=s->prev;\
+                       }\
+               copy->prev=NULL;\
+               copy=new-1;\
+               }\
+       else\
+               copy=NULL;\
+}
+
+
+#define BBEND(s,i){\
+       i=stackdepth-1;\
+       copy=s;\
+       while(copy){\
+               if((copy->varkind==STACKVAR)&&(copy->varnum>i))\
+                       copy->varkind=TEMPVAR;\
+               else {\
+                       copy->varkind=STACKVAR;\
+                       copy->varnum=i;\
+                       }\
+               interfaces[i][copy->type].type = copy->type;\
+               interfaces[i][copy->type].flags |= copy->flags;\
+               i--;copy=copy->prev;\
+               }\
+       i=bptr->indepth-1;\
+       copy=bptr->instack;\
+       while(copy){\
+               interfaces[i][copy->type].type = copy->type;\
+               if(copy->varkind==STACKVAR){\
+                       if (copy->flags & SAVEDVAR)\
+                               interfaces[i][copy->type].flags |= SAVEDVAR;\
+                       }\
+               i--;copy=copy->prev;\
+               }\
+}
+
+       
+#define MARKREACHED(b,c) {\
+       if(b->flags<0)\
+               {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;}\
+       else {stackptr s=curstack;stackptr t=b->instack;\
+               if(b->indepth!=stackdepth)\
+                       {show_icmd_method();panic("Stack depth mismatch");}\
+               while(s){if (s->type!=t->type)\
+                               TYPEPANIC\
+                       s=s->prev;t=t->prev;\
+                       }\
+               }\
+}
+
+
+static void show_icmd_method();
+
+static void analyse_stack()
+{
+       int b_count;
+       int stackdepth;
+       stackptr curstack, new, copy;
+       int opcode, i, len, loops;
+       int superblockend, repeat, deadcode;
+       instruction *iptr = instr;
+       basicblock *bptr, *tbptr;
+       s4  *s4ptr;
+       
+       arguments_num = 0;
+       new = stack;
+       loops = 0;
+       block[0].flags = BBREACHED;
+       block[0].instack = 0;
+       block[0].indepth = 0;
+
+       for (i = 0; i < exceptiontablelength; i++) {
+               bptr = &block[block_index[extable[i].handlerpc]];
+               bptr->flags = BBREACHED;
+               bptr->type = BBTYPE_EXH;
+               bptr->instack = new;
+               bptr->indepth = 1;
+               STACKRESET;
+               NEWXSTACK;
+               }
+
+       do {
+               loops++;
+               b_count = block_count;
+               bptr = block;
+               superblockend = true;
+               repeat = false;
+               STACKRESET;
+               deadcode = true;
+               while (--b_count >= 0) {
+                       if (superblockend && (bptr->flags < BBREACHED))
+                               repeat = true;
+                       else if (bptr->flags <= BBREACHED) {
+                               if (superblockend)
+                                       stackdepth = bptr->indepth;
+                               else if (bptr->flags < BBREACHED) {
+                                       COPYCURSTACK(copy);
+                                       bptr->instack = copy;
+                                       bptr->indepth = stackdepth;
+                                       }
+                               else if (bptr->indepth != stackdepth) {
+                                       show_icmd_method();
+                                       panic("Stack depth mismatch");
+                                       
+                                       }
+                               curstack = bptr->instack;
+                               deadcode = false;
+                               superblockend = false;
+                               bptr->flags = BBFINISHED;
+                               i = bptr[0].ipc;
+                               len = bptr[1].ipc - i;
+                               iptr = &instr[i];
+                               while (--len >= 0)  {
+                                       opcode = iptr->opc;
+                                       switch (opcode) {
+
+                                               /* pop 0 push 0 */
+
+                                               case ICMD_NOP:
+                                               case ICMD_CHECKASIZE:
+                                                       SETDST;
+                                                       break;
+                                               case ICMD_RET:
+                                                       locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
+                                               case ICMD_RETURN:
+                                                       COUNT(count_pcmd_return);
+                                                       SETDST;
+                                                       superblockend = true;
+                                                       break;
+
+                                               /* pop 0 push 1 const */
+                                               
+                                               case ICMD_ICONST:
+                                                       COUNT(count_pcmd_load);
+                                                       if (len > 0) {
+                                                               switch (iptr[1].opc) {
+                                                                       case ICMD_IADD:
+                                                                               iptr[0].opc = ICMD_IADDCONST;
+icmd_iconst_tail:
+                                                                               iptr[1].opc = ICMD_NOP;
+                                                                               OP1_1(TYPE_INT,TYPE_INT);
+                                                                               COUNT(count_pcmd_op);
+                                                                               break;
+                                                                       case ICMD_ISUB:
+                                                                               iptr[0].opc = ICMD_ISUBCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IMUL:
+                                                                               iptr[0].opc = ICMD_IMULCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IAND:
+                                                                               iptr[0].opc = ICMD_IANDCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IOR:
+                                                                               iptr[0].opc = ICMD_IORCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IXOR:
+                                                                               iptr[0].opc = ICMD_IXORCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_ISHL:
+                                                                               iptr[0].opc = ICMD_ISHLCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_ISHR:
+                                                                               iptr[0].opc = ICMD_ISHRCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IUSHR:
+                                                                               iptr[0].opc = ICMD_IUSHRCONST;
+                                                                               goto icmd_iconst_tail;
+                                                                       case ICMD_IF_ICMPEQ:
+                                                                               iptr[0].opc = ICMD_IFEQ;
+icmd_if_icmp_tail:
+                                                                               iptr[0].op1 = iptr[1].op1;
+                                                                               iptr[1].opc = ICMD_NOP;
+                                                                               OP1_0(TYPE_INT);
+                                                                               tbptr = block + block_index[iptr->op1];
+                                                                               MARKREACHED(tbptr, copy);
+                                                                               COUNT(count_pcmd_bra);
+                                                                               break;
+                                                                       case ICMD_IF_ICMPLT:
+                                                                               iptr[0].opc = ICMD_IFLT;
+                                                                               goto icmd_if_icmp_tail;
+                                                                       case ICMD_IF_ICMPLE:
+                                                                               iptr[0].opc = ICMD_IFLE;
+                                                                               goto icmd_if_icmp_tail;
+                                                                       case ICMD_IF_ICMPNE:
+                                                                               iptr[0].opc = ICMD_IFNE;
+                                                                               goto icmd_if_icmp_tail;
+                                                                       case ICMD_IF_ICMPGT:
+                                                                               iptr[0].opc = ICMD_IFGT;
+                                                                               goto icmd_if_icmp_tail;
+                                                                       case ICMD_IF_ICMPGE:
+                                                                               iptr[0].opc = ICMD_IFGE;
+                                                                               goto icmd_if_icmp_tail;
+                                                                       default:
+                                                                               CONST(TYPE_INT);
+                                                                       }
+                                                               }
+                                                       else
+                                                               CONST(TYPE_INT);
+                                                       break;
+                                               case ICMD_LCONST:
+                                                       COUNT(count_pcmd_load);
+                                                       if (len > 0) {
+                                                               switch (iptr[1].opc) {
+                                                                       case ICMD_LADD:
+                                                                               iptr[0].opc = ICMD_LADDCONST;
+icmd_lconst_tail:
+                                                                               iptr[1].opc = ICMD_NOP;
+                                                                               OP1_1(TYPE_LNG,TYPE_LNG);
+                                                                               COUNT(count_pcmd_op);
+                                                                               break;
+                                                                       case ICMD_LSUB:
+                                                                               iptr[0].opc = ICMD_LSUBCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LMUL:
+                                                                               iptr[0].opc = ICMD_LMULCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LAND:
+                                                                               iptr[0].opc = ICMD_LANDCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LOR:
+                                                                               iptr[0].opc = ICMD_LORCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LXOR:
+                                                                               iptr[0].opc = ICMD_LXORCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LSHL:
+                                                                               iptr[0].opc = ICMD_LSHLCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LSHR:
+                                                                               iptr[0].opc = ICMD_LSHRCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LUSHR:
+                                                                               iptr[0].opc = ICMD_LUSHRCONST;
+                                                                               goto icmd_lconst_tail;
+                                                                       case ICMD_LCMP:
+                                                                               if ((len > 1) && (iptr[2].val.i == 0)) {
+                                                                                       switch (iptr[2].opc) {
+                                                                                       case ICMD_IFEQ:
+                                                                                               iptr[0].opc = ICMD_IF_LEQ;
+icmd_lconst_lcmp_tail:
+                                                                                               iptr[0].op1 = iptr[2].op1;
+                                                                                               iptr[1].opc = ICMD_NOP;
+                                                                                               iptr[2].opc = ICMD_NOP;
+                                                                                               OP1_0(TYPE_LNG);
+                                                                                               tbptr = block + block_index[iptr->op1];
+                                                                                               MARKREACHED(tbptr, copy);
+                                                                                               COUNT(count_pcmd_bra);
+                                                                                               COUNT(count_pcmd_op);
+                                                                                               break;
+                                                                                       case ICMD_IFNE:
+                                                                                               iptr[0].opc = ICMD_IF_LNE;
+                                                                                               goto icmd_lconst_lcmp_tail;
+                                                                                       case ICMD_IFLT:
+                                                                                               iptr[0].opc = ICMD_IF_LLT;
+                                                                                               goto icmd_lconst_lcmp_tail;
+                                                                                       case ICMD_IFGT:
+                                                                                               iptr[0].opc = ICMD_IF_LGT;
+                                                                                               goto icmd_lconst_lcmp_tail;
+                                                                                       case ICMD_IFLE:
+                                                                                               iptr[0].opc = ICMD_IF_LLE;
+                                                                                               goto icmd_lconst_lcmp_tail;
+                                                                                       case ICMD_IFGE:
+                                                                                               iptr[0].opc = ICMD_IF_LGE;
+                                                                                               goto icmd_lconst_lcmp_tail;
+                                                                                       default:
+                                                                                               CONST(TYPE_LNG);
+                                                                                       } /* switch (iptr[2].opc) */
+                                                                                       } /* if (iptr[2].val.i == 0) */
+                                                                               else
+                                                                                       CONST(TYPE_LNG);
+                                                                               break;
+                                                                       default:
+                                                                               CONST(TYPE_LNG);
+                                                                       }
+                                                               }
+                                                       else
+                                                               CONST(TYPE_LNG);
+                                                       break;
+                                               case ICMD_FCONST:
+                                                       COUNT(count_pcmd_load);
+                                                       CONST(TYPE_FLT);
+                                                       break;
+                                               case ICMD_DCONST:
+                                                       COUNT(count_pcmd_load);
+                                                       CONST(TYPE_DBL);
+                                                       break;
+                                               case ICMD_ACONST:
+                                                       COUNT(count_pcmd_load);
+                                                       CONST(TYPE_ADR);
+                                                       break;
+
+                                               /* pop 0 push 1 load */
+                                               
+                                               case ICMD_ILOAD:
+                                               case ICMD_LLOAD:
+                                               case ICMD_FLOAD:
+                                               case ICMD_DLOAD:
+                                               case ICMD_ALOAD:
+                                                       COUNT(count_load_instruction);
+                                                       i = opcode-ICMD_ILOAD;
+                                                       locals[iptr->op1][i].type = i;
+                                                       LOAD(i, LOCALVAR, iptr->op1);
+                                                       break;
+
+                                               /* pop 2 push 1 */
+
+                                               case ICMD_IALOAD:
+                                               case ICMD_LALOAD:
+                                               case ICMD_FALOAD:
+                                               case ICMD_DALOAD:
+                                               case ICMD_AALOAD:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_check_bound);
+                                                       COUNT(count_pcmd_mem);
+                                                       OP2IAT_1(opcode-ICMD_IALOAD);
+                                                       break;
+
+                                               case ICMD_BALOAD:
+                                               case ICMD_CALOAD:
+                                               case ICMD_SALOAD:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_check_bound);
+                                                       COUNT(count_pcmd_mem);
+                                                       OP2IAT_1(TYPE_INT);
+                                                       break;
+
+                                               /* pop 0 push 0 iinc */
+
+                                               case ICMD_IINC:
+#ifdef STATISTICS
+                                                       i = stackdepth;
+                                                       if (i >= 10)
+                                                               count_store_depth[10]++;
+                                                       else
+                                                               count_store_depth[i]++;
+#endif
+                                                       copy = curstack;
+                                                       i = stackdepth - 1;
+                                                       while (copy) {
+                                                               if ((copy->varkind == LOCALVAR) &&
+                                                                   (copy->varnum == curstack->varnum)) {
+                                                                       copy->varkind = TEMPVAR;
+                                                                       copy->varnum = i;
+                                                                       }
+                                                               i--;
+                                                               copy = copy->prev;
+                                                               }
+                                                       SETDST;
+                                                       break;
+
+                                               /* pop 1 push 0 store */
+
+                                               case ICMD_ISTORE:
+                                               case ICMD_LSTORE:
+                                               case ICMD_FSTORE:
+                                               case ICMD_DSTORE:
+                                               case ICMD_ASTORE:
+                                                       i = opcode-ICMD_ISTORE;
+                                                       locals[iptr->op1][i].type = i;
+#ifdef STATISTICS
+                                                       count_pcmd_store++;
+                                                       i = new - curstack;
+                                                       if (i >= 20)
+                                                               count_store_length[20]++;
+                                                       else
+                                                               count_store_length[i]++;
+                                                       i = stackdepth - 1;
+                                                       if (i >= 10)
+                                                               count_store_depth[10]++;
+                                                       else
+                                                               count_store_depth[i]++;
+#endif
+                                                       copy = curstack->prev;
+                                                       i = stackdepth - 2;
+                                                       while (copy) {
+                                                               if ((copy->varkind == LOCALVAR) &&
+                                                                   (copy->varnum == curstack->varnum)) {
+                                                                       copy->varkind = TEMPVAR;
+                                                                       copy->varnum = i;
+                                                                       }
+                                                               i--;
+                                                               copy = copy->prev;
+                                                               }
+                                                       if ((new - curstack) == 1) {
+                                                               curstack->varkind = LOCALVAR;
+                                                               curstack->varnum = iptr->op1;
+                                                               };
+                                                       STORE(opcode-ICMD_ISTORE);
+                                                       break;
+
+                                               /* pop 3 push 0 */
+
+                                               case ICMD_IASTORE:
+                                               case ICMD_LASTORE:
+                                               case ICMD_FASTORE:
+                                               case ICMD_DASTORE:
+                                               case ICMD_AASTORE:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_check_bound);
+                                                       COUNT(count_pcmd_mem);
+                                                       OP3TIA_0(opcode-ICMD_IASTORE);
+                                                       break;
+                                               case ICMD_BASTORE:
+                                               case ICMD_CASTORE:
+                                               case ICMD_SASTORE:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_check_bound);
+                                                       COUNT(count_pcmd_mem);
+                                                       OP3TIA_0(TYPE_INT);
+                                                       break;
+
+                                               /* pop 1 push 0 */
+
+                                               case ICMD_POP:
+                                                       OP1_0ANY;
+                                                       break;
+
+                                               case ICMD_IRETURN:
+                                               case ICMD_LRETURN:
+                                               case ICMD_FRETURN:
+                                               case ICMD_DRETURN:
+                                               case ICMD_ARETURN:
+                                                       COUNT(count_pcmd_return);
+                                                       OP1_0(opcode-ICMD_IRETURN);
+                                                       superblockend = true;
+                                                       break;
+
+                                               case ICMD_ATHROW:
+                                                       COUNT(count_check_null);
+                                                       OP1_0(TYPE_ADR);
+                                                       STACKRESET;
+                                                       SETDST;
+                                                       superblockend = true;
+                                                       break;
+
+                                               case ICMD_PUTSTATIC:
+                                                       COUNT(count_pcmd_mem);
+                                                       OP1_0(iptr->op1);
+                                                       break;
+
+                                               /* pop 1 push 0 branch */
+
+                                               case ICMD_IFNULL:
+                                               case ICMD_IFNONNULL:
+                                                       COUNT(count_pcmd_bra);
+                                                       OP1_0(TYPE_ADR);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       MARKREACHED(tbptr, copy);
+                                                       break;
+
+                                               case ICMD_IFEQ:
+                                               case ICMD_IFNE:
+                                               case ICMD_IFLT:
+                                               case ICMD_IFGE:
+                                               case ICMD_IFGT:
+                                               case ICMD_IFLE:
+                                                       COUNT(count_pcmd_bra);
+                                                       OP1_0(TYPE_INT);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       MARKREACHED(tbptr, copy);
+                                                       break;
+
+                                               /* pop 0 push 0 branch */
+
+                                               case ICMD_GOTO:
+                                                       COUNT(count_pcmd_bra);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       MARKREACHED(tbptr, copy);
+                                                       SETDST;
+                                                       superblockend = true;
+                                                       break;
+
+                                               /* pop 1 push 0 table branch */
+
+                                               case ICMD_TABLESWITCH:
+                                                       COUNT(count_pcmd_table);
+                                                       OP1_0(TYPE_INT);
+                                                       s4ptr = iptr->val.a;
+                                                       tbptr = block + block_index[*s4ptr++]; /* default */
+                                                       MARKREACHED(tbptr, copy);
+                                                       i = *s4ptr++;                          /* low     */
+                                                       i = *s4ptr++ - i + 1;                  /* high    */
+                                                       while (--i >= 0) {
+                                                               tbptr = block + block_index[*s4ptr++];
+                                                               MARKREACHED(tbptr, copy);
+                                                               }
+                                                       SETDST;
+                                                       superblockend = true;
+                                                       break;
+                                                       
+                                               /* pop 1 push 0 table branch */
+
+                                               case ICMD_LOOKUPSWITCH:
+                                                       COUNT(count_pcmd_table);
+                                                       OP1_0(TYPE_INT);
+                                                       s4ptr = iptr->val.a;
+                                                       tbptr = block + block_index[*s4ptr++]; /* default */
+                                                       MARKREACHED(tbptr, copy);
+                                                       i = *s4ptr++;                          /* count   */
+                                                       while (--i >= 0) {
+                                                               tbptr = block + block_index[s4ptr[1]];
+                                                               MARKREACHED(tbptr, copy);
+                                                               s4ptr += 2;
+                                                               }
+                                                       SETDST;
+                                                       superblockend = true;
+                                                       break;
+
+                                               case ICMD_NULLCHECKPOP:
+                                               case ICMD_MONITORENTER:
+                                                       COUNT(count_check_null);
+                                               case ICMD_MONITOREXIT:
+                                                       OP1_0(TYPE_ADR);
+                                                       break;
+
+                                               /* pop 2 push 0 branch */
+
+                                               case ICMD_IF_ICMPEQ:
+                                               case ICMD_IF_ICMPNE:
+                                               case ICMD_IF_ICMPLT:
+                                               case ICMD_IF_ICMPGE:
+                                               case ICMD_IF_ICMPGT:
+                                               case ICMD_IF_ICMPLE:
+                                                       COUNT(count_pcmd_bra);
+                                                       OP2_0(TYPE_INT);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       MARKREACHED(tbptr, copy);
+                                                       break;
+
+                                               case ICMD_IF_ACMPEQ:
+                                               case ICMD_IF_ACMPNE:
+                                                       COUNT(count_pcmd_bra);
+                                                       OP2_0(TYPE_ADR);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       MARKREACHED(tbptr, copy);
+                                                       break;
+
+                                               /* pop 2 push 0 */
+
+                                               case ICMD_PUTFIELD:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_pcmd_mem);
+                                                       OPTT2_0(iptr->op1,TYPE_ADR);
+                                                       break;
+
+                                               case ICMD_POP2:
+                                                       if (! IS_2_WORD_TYPE(curstack->type)) {
+                                                               OP1_0ANY;                /* second pop */
+                                                               }
+                                                       else
+                                                               iptr->opc = ICMD_POP;
+                                                       OP1_0ANY;
+                                                       break;
+
+                                               /* pop 0 push 1 dup */
+                                               
+                                               case ICMD_DUP:
+                                                       COUNT(count_dup_instruction);
+                                                       DUP;
+                                                       break;
+
+                                               case ICMD_DUP2:
+                                                       if (IS_2_WORD_TYPE(curstack->type)) {
+                                                               iptr->opc = ICMD_DUP;
+                                                               DUP;
+                                                               }
+                                                       else {
+                                                               copy = curstack;
+                                                               NEWSTACK(copy[-1].type, copy[-1].varkind,
+                                                                        copy[-1].varnum);
+                                                               NEWSTACK(copy[ 0].type, copy[ 0].varkind,
+                                                                        copy[ 0].varnum);
+                                                               SETDST;
+                                                               stackdepth+=2;
+                                                               }
+                                                       break;
+
+                                               /* pop 2 push 3 dup */
+                                               
+                                               case ICMD_DUP_X1:
+                                                       DUP_X1;
+                                                       break;
+
+                                               case ICMD_DUP2_X1:
+                                                       if (IS_2_WORD_TYPE(curstack->type)) {
+                                                               iptr->opc = ICMD_DUP_X1;
+                                                               DUP_X1;
+                                                               }
+                                                       else {
+                                                               DUP2_X1;
+                                                               }
+                                                       break;
+
+                                               /* pop 3 push 4 dup */
+                                               
+                                               case ICMD_DUP_X2:
+                                                       if (IS_2_WORD_TYPE(curstack[-1].type)) {
+                                                               iptr->opc = ICMD_DUP_X1;
+                                                               DUP_X1;
+                                                               }
+                                                       else {
+                                                               DUP_X2;
+                                                               }
+                                                       break;
+
+                                               case ICMD_DUP2_X2:
+                                                       if (IS_2_WORD_TYPE(curstack->type)) {
+                                                               if (IS_2_WORD_TYPE(curstack[-1].type)) {
+                                                                       iptr->opc = ICMD_DUP_X1;
+                                                                       DUP_X1;
+                                                                       }
+                                                               else {
+                                                                       iptr->opc = ICMD_DUP_X2;
+                                                                       DUP_X2;
+                                                                       }
+                                                               }
+                                                       else
+                                                               if (IS_2_WORD_TYPE(curstack[-2].type)) {
+                                                                       iptr->opc = ICMD_DUP2_X1;
+                                                                       DUP2_X1;
+                                                                       }
+                                                               else {
+                                                                       DUP2_X2;
+                                                                       }
+                                                       break;
+
+                                               /* pop 2 push 2 swap */
+                                               
+                                               case ICMD_SWAP:
+                                                       SWAP;
+                                                       break;
+
+                                               /* pop 2 push 1 */
+                                               
+                                               case ICMD_IADD:
+                                               case ICMD_ISUB:
+                                               case ICMD_IMUL:
+                                               case ICMD_IDIV:
+                                               case ICMD_IREM:
+
+                                               case ICMD_ISHL:
+                                               case ICMD_ISHR:
+                                               case ICMD_IUSHR:
+                                               case ICMD_IAND:
+                                               case ICMD_IOR:
+                                               case ICMD_IXOR:
+                                                       COUNT(count_pcmd_op);
+                                                       OP2_1(TYPE_INT);
+                                                       break;
+
+                                               case ICMD_LADD:
+                                               case ICMD_LSUB:
+                                               case ICMD_LMUL:
+                                               case ICMD_LDIV:
+                                               case ICMD_LREM:
+
+                                               case ICMD_LOR:
+                                               case ICMD_LAND:
+                                               case ICMD_LXOR:
+                                                       COUNT(count_pcmd_op);
+                                                       OP2_1(TYPE_LNG);
+                                                       break;
+
+                                               case ICMD_LSHL:
+                                               case ICMD_LSHR:
+                                               case ICMD_LUSHR:
+                                                       COUNT(count_pcmd_op);
+                                                       OP2IT_1(TYPE_LNG);
+                                                       break;
+
+                                               case ICMD_FADD:
+                                               case ICMD_FSUB:
+                                               case ICMD_FMUL:
+                                               case ICMD_FDIV:
+                                               case ICMD_FREM:
+                                                       COUNT(count_pcmd_op);
+                                                       OP2_1(TYPE_FLT);
+                                                       break;
+
+                                               case ICMD_DADD:
+                                               case ICMD_DSUB:
+                                               case ICMD_DMUL:
+                                               case ICMD_DDIV:
+                                               case ICMD_DREM:
+                                                       COUNT(count_pcmd_op);
+                                                       OP2_1(TYPE_DBL);
+                                                       break;
+
+                                               case ICMD_LCMP:
+                                                       COUNT(count_pcmd_op);
+                                                       if ((len > 0) && (iptr[1].val.i == 0)) {
+                                                               switch (iptr[1].opc) {
+                                                                       case ICMD_IFEQ:
+                                                                               iptr[0].opc = ICMD_IF_LCMPEQ;
+icmd_lcmp_if_tail:
+                                                                               iptr[0].op1 = iptr[1].op1;
+                                                                               iptr[1].opc = ICMD_NOP;
+                                                                               OP2_0(TYPE_LNG);
+                                                                               tbptr = block + block_index[iptr->op1];
+                                                                               MARKREACHED(tbptr, copy);
+                                                                               COUNT(count_pcmd_bra);
+                                                                               break;
+                                                                       case ICMD_IFNE:
+                                                                               iptr[0].opc = ICMD_IF_LCMPNE;
+                                                                               goto icmd_lcmp_if_tail;
+                                                                       case ICMD_IFLT:
+                                                                               iptr[0].opc = ICMD_IF_LCMPLT;
+                                                                               goto icmd_lcmp_if_tail;
+                                                                       case ICMD_IFGT:
+                                                                               iptr[0].opc = ICMD_IF_LCMPGT;
+                                                                               goto icmd_lcmp_if_tail;
+                                                                       case ICMD_IFLE:
+                                                                               iptr[0].opc = ICMD_IF_LCMPLE;
+                                                                               goto icmd_lcmp_if_tail;
+                                                                       case ICMD_IFGE:
+                                                                               iptr[0].opc = ICMD_IF_LCMPGE;
+                                                                               goto icmd_lcmp_if_tail;
+                                                                       default:
+                                                                               OPTT2_1(TYPE_LNG, TYPE_INT);
+                                                                       }
+                                                               }
+                                                       else
+                                                               OPTT2_1(TYPE_LNG, TYPE_INT);
+                                                       break;
+                                               case ICMD_FCMPL:
+                                               case ICMD_FCMPG:
+                                                       COUNT(count_pcmd_op);
+                                                       OPTT2_1(TYPE_FLT, TYPE_INT);
+                                                       break;
+                                               case ICMD_DCMPL:
+                                               case ICMD_DCMPG:
+                                                       COUNT(count_pcmd_op);
+                                                       OPTT2_1(TYPE_DBL, TYPE_INT);
+                                                       break;
+
+                                               /* pop 1 push 1 */
+                                               
+                                               case ICMD_INEG:
+                                               case ICMD_INT2BYTE:
+                                               case ICMD_INT2CHAR:
+                                               case ICMD_INT2SHORT:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_INT, TYPE_INT);
+                                                       break;
+                                               case ICMD_LNEG:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_LNG, TYPE_LNG);
+                                                       break;
+                                               case ICMD_FNEG:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_FLT, TYPE_FLT);
+                                                       break;
+                                               case ICMD_DNEG:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_DBL, TYPE_DBL);
+                                                       break;
+
+                                               case ICMD_I2L:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_INT, TYPE_LNG);
+                                                       break;
+                                               case ICMD_I2F:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_INT, TYPE_FLT);
+                                                       break;
+                                               case ICMD_I2D:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_INT, TYPE_DBL);
+                                                       break;
+                                               case ICMD_L2I:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_LNG, TYPE_INT);
+                                                       break;
+                                               case ICMD_L2F:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_LNG, TYPE_FLT);
+                                                       break;
+                                               case ICMD_L2D:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_LNG, TYPE_DBL);
+                                                       break;
+                                               case ICMD_F2I:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_FLT, TYPE_INT);
+                                                       break;
+                                               case ICMD_F2L:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_FLT, TYPE_LNG);
+                                                       break;
+                                               case ICMD_F2D:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_FLT, TYPE_DBL);
+                                                       break;
+                                               case ICMD_D2I:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_DBL, TYPE_INT);
+                                                       break;
+                                               case ICMD_D2L:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_DBL, TYPE_LNG);
+                                                       break;
+                                               case ICMD_D2F:
+                                                       COUNT(count_pcmd_op);
+                                                       OP1_1(TYPE_DBL, TYPE_FLT);
+                                                       break;
+
+                                               case ICMD_CHECKCAST:
+                                                       OP1_1(TYPE_ADR, TYPE_ADR);
+                                                       break;
+
+                                               case ICMD_ARRAYLENGTH:
+                                               case ICMD_INSTANCEOF:
+                                                       OP1_1(TYPE_ADR, TYPE_INT);
+                                                       break;
+
+                                               case ICMD_NEWARRAY:
+                                               case ICMD_ANEWARRAY:
+                                                       OP1_1(TYPE_INT, TYPE_ADR);
+                                                       break;
+
+                                               case ICMD_GETFIELD:
+                                                       COUNT(count_check_null);
+                                                       COUNT(count_pcmd_mem);
+                                                       OP1_1(TYPE_ADR, iptr->op1);
+                                                       break;
+
+                                               /* pop 0 push 1 */
+                                               
+                                               case ICMD_GETSTATIC:
+                                                       COUNT(count_pcmd_mem);
+                                                       OP0_1(iptr->op1);
+                                                       break;
+
+                                               case ICMD_NEW:
+                                                       OP0_1(TYPE_ADR);
+                                                       break;
+
+                                               case ICMD_JSR:
+                                                       OP0_1(TYPE_ADR);
+                                                       tbptr = block + block_index[iptr->op1];
+                                                       tbptr->type=BBTYPE_SBR;
+                                                       MARKREACHED(tbptr, copy);
+                                                       OP1_0ANY;
+                                                       break;
+
+                                               /* pop many push any */
+                                               
+                                               case ICMD_INVOKEVIRTUAL:
+                                               case ICMD_INVOKESPECIAL:
+                                               case ICMD_INVOKEINTERFACE:
+                                               case ICMD_INVOKESTATIC:
+                                                       COUNT(count_pcmd_met);
+                                                       {
+                                                       methodinfo *m = iptr->val.a;
+                                                       if (m->flags & ACC_STATIC)
+                                                               {COUNT(count_check_null);}
+                                                       i = iptr->op1;
+                                                       if (i > arguments_num)
+                                                               arguments_num = i;
+                                                       copy = curstack;
+                                                       while (--i >= 0) {
+                                                               if (! (copy->flags & SAVEDVAR)) {
+                                                                       copy->varkind = ARGVAR;
+                                                                       copy->varnum = i;
+                                                                       }
+                                                               copy = copy->prev;
+                                                               }
+                                                       while (copy) {
+                                                               copy->flags |= SAVEDVAR;
+                                                               copy = copy->prev;
+                                                               }
+                                                       i = iptr->op1;
+                                                       POPMANY(i);
+                                                       if (m->returntype != TYPE_VOID) {
+                                                               OP0_1(m->returntype);
+                                                               }
+                                                       break;
+                                                       }
+
+                                               case ICMD_BUILTIN3:
+                                                       if (! (curstack->flags & SAVEDVAR)) {
+                                                               curstack->varkind = ARGVAR;
+                                                               curstack->varnum = 2;
+                                                               }
+                                                       OP1_0ANY;
+                                               case ICMD_BUILTIN2:
+                                                       if (! (curstack->flags & SAVEDVAR)) {
+                                                               curstack->varkind = ARGVAR;
+                                                               curstack->varnum = 1;
+                                                               }
+                                                       OP1_0ANY;
+                                               case ICMD_BUILTIN1:
+                                                       if (! (curstack->flags & SAVEDVAR)) {
+                                                               curstack->varkind = ARGVAR;
+                                                               curstack->varnum = 0;
+                                                               }
+                                                       OP1_0ANY;
+                                                       copy = curstack;
+                                                       while (copy) {
+                                                               copy->flags |= SAVEDVAR;
+                                                               copy = copy->prev;
+                                                               }
+                                                       if (iptr->op1 != TYPE_VOID)
+                                                               OP0_1(iptr->op1);
+                                                       break;
+
+                                               case ICMD_MULTIANEWARRAY:
+                                                       i = iptr->op1;
+                                                       if ((i + intreg_argnum) > arguments_num)
+                                                               arguments_num = i + intreg_argnum;
+                                                       copy = curstack;
+                                                       while (--i >= 0) {
+                                                               if (! (copy->flags & SAVEDVAR)) {
+                                                                       copy->varkind = ARGVAR;
+                                                                       copy->varnum = i + intreg_argnum;
+                                                                       }
+                                                               copy = copy->prev;
+                                                               }
+                                                       while (copy) {
+                                                               copy->flags |= SAVEDVAR;
+                                                               copy = copy->prev;
+                                                               }
+                                                       i = iptr->op1;
+                                                       POPMANY(i);
+                                                       OP0_1(TYPE_ADR);
+                                                       break;
+
+                                               default:
+                                                       printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
+                                                       panic("Missing ICMD code during stack analysis");
+                                               } /* switch */
+                                       iptr++;
+                                       } /* while instructions */
+                               bptr->outstack = curstack;
+                               bptr->outdepth = stackdepth;
+                               BBEND(curstack, i);
+                               } /* if */
+                       else
+                               superblockend = true;
+                       bptr++;
+               } /* while blocks */
+       } while (repeat && ! deadcode);
+
+#ifdef STATISTICS
+       if (block_count > count_max_basic_blocks)
+               count_max_basic_blocks = block_count;
+       count_basic_blocks += block_count;
+       if (block[block_count].ipc > count_max_javainstr)
+               count_max_javainstr = block[block_count].ipc;
+       count_javainstr += block[block_count].ipc;
+       if (stack_count > count_upper_bound_new_stack)
+               count_upper_bound_new_stack = stack_count;
+       if ((new - stack) > count_max_new_stack)
+               count_max_new_stack = (new - stack);
+
+       b_count = block_count;
+       bptr = block;
+       while (--b_count >= 0) {
+               if (bptr->flags > BBREACHED) {
+                       if (bptr->indepth >= 10)
+                               count_block_stack[10]++;
+                       else
+                               count_block_stack[bptr->indepth]++;
+                       len = bptr[1].ipc - bptr[0].ipc;
+                       if (len <= 10) 
+                               count_block_size_distribution[len - 1]++;
+                       else if (len <= 12)
+                               count_block_size_distribution[10]++;
+                       else if (len <= 14)
+                               count_block_size_distribution[11]++;
+                       else if (len <= 16)
+                               count_block_size_distribution[12]++;
+                       else if (len <= 18)
+                               count_block_size_distribution[13]++;
+                       else if (len <= 20)
+                               count_block_size_distribution[14]++;
+                       else if (len <= 25)
+                               count_block_size_distribution[15]++;
+                       else if (len <= 30)
+                               count_block_size_distribution[16]++;
+                       else
+                               count_block_size_distribution[17]++;
+                       }
+               bptr++;
+               }
+
+       if (loops == 1)
+               count_analyse_iterations[0]++;
+       else if (loops == 2)
+               count_analyse_iterations[1]++;
+       else if (loops == 3)
+               count_analyse_iterations[2]++;
+       else if (loops == 4)
+               count_analyse_iterations[3]++;
+       else
+               count_analyse_iterations[4]++;
+
+       if (block_count <= 5)
+               count_method_bb_distribution[0]++;
+       else if (block_count <= 10)
+               count_method_bb_distribution[1]++;
+       else if (block_count <= 15)
+               count_method_bb_distribution[2]++;
+       else if (block_count <= 20)
+               count_method_bb_distribution[3]++;
+       else if (block_count <= 30)
+               count_method_bb_distribution[4]++;
+       else if (block_count <= 40)
+               count_method_bb_distribution[5]++;
+       else if (block_count <= 50)
+               count_method_bb_distribution[6]++;
+       else if (block_count <= 75)
+               count_method_bb_distribution[7]++;
+       else
+               count_method_bb_distribution[8]++;
+#endif
+}
+
+
+static void print_stack(stackptr s) {
+       int i, j;
+       stackptr t;
+
+       i = maxstack;
+       t = s;
+       
+       while (t) {
+               i--;
+               t = t->prev;
+               }
+       j = maxstack - i;
+       while (--i >= 0)
+               printf("    ");
+       while (s) {
+               j--;
+               if (s->flags & SAVEDVAR)
+                       switch (s->varkind) {
+                               case TEMPVAR:
+                                       if (s->flags & INMEMORY)
+                                               printf(" m%02d", s->regoff);
+                                       else
+                                               printf(" r%02d", s->regoff);
+                                       break;
+                               case STACKVAR:
+                                       printf(" s%02d", s->varnum);
+                                       break;
+                               case LOCALVAR:
+                                       printf(" l%02d", s->varnum);
+                                       break;
+                               case ARGVAR:
+                                       printf(" a%02d", s->varnum);
+                                       break;
+                               default:
+                                       printf(" !%02d", j);
+                               }
+               else
+                       switch (s->varkind) {
+                               case TEMPVAR:
+                                       if (s->flags & INMEMORY)
+                                               printf(" M%02d", s->regoff);
+                                       else
+                                               printf(" R%02d", s->regoff);
+                                       break;
+                               case STACKVAR:
+                                       printf(" S%02d", s->varnum);
+                                       break;
+                               case LOCALVAR:
+                                       printf(" L%02d", s->varnum);
+                                       break;
+                               case ARGVAR:
+                                       printf(" A%02d", s->varnum);
+                                       break;
+                               default:
+                                       printf(" ?%02d", j);
+                               }
+               s = s->prev;
+               }
+}
+
+
+static void print_reg(stackptr s) {
+       if (s) {
+               if (s->flags & SAVEDVAR)
+                       switch (s->varkind) {
+                               case TEMPVAR:
+                                       if (s->flags & INMEMORY)
+                                               printf(" tm%02d", s->regoff);
+                                       else
+                                               printf(" tr%02d", s->regoff);
+                                       break;
+                               case STACKVAR:
+                                       printf(" s %02d", s->varnum);
+                                       break;
+                               case LOCALVAR:
+                                       printf(" l %02d", s->varnum);
+                                       break;
+                               case ARGVAR:
+                                       printf(" a %02d", s->varnum);
+                                       break;
+                               default:
+                                       printf(" ! %02d", s->varnum);
+                               }
+               else
+                       switch (s->varkind) {
+                               case TEMPVAR:
+                                       if (s->flags & INMEMORY)
+                                               printf(" Tm%02d", s->regoff);
+                                       else
+                                               printf(" Tr%02d", s->regoff);
+                                       break;
+                               case STACKVAR:
+                                       printf(" S %02d", s->varnum);
+                                       break;
+                               case LOCALVAR:
+                                       printf(" L %02d", s->varnum);
+                                       break;
+                               case ARGVAR:
+                                       printf(" A %02d", s->varnum);
+                                       break;
+                               default:
+                                       printf(" ? %02d", s->varnum);
+                               }
+               }
+       else
+               printf("     ");
+               
+}
+
+
+static char *builtin_name(functionptr bptr)
+{
+       builtin_descriptor *bdesc = builtin_desc;
+       while ((bdesc->bptr != NULL) && (bdesc->bptr != bptr))
+               bdesc++;
+       return bdesc->name;
+}
+
+
+static void show_icmd_method()
+{
+       int b, i, j;
+       int deadcode;
+       s4  *s4ptr;
+       
+       printf("\n");
+       unicode_fprint(stdout, class->name);
+       printf(".");
+       unicode_fprint(stdout, method->name);
+       printf(" ");
+       unicode_fprint(stdout, method->descriptor);
+       printf ("\n\nMax locals: %d\n", (int) maxlocals);
+       printf ("Max stack:  %d\n", (int) maxstack);
+
+       printf ("Exceptions:\n");
+       for (i = 0; i < exceptiontablelength; i++) {
+               printf("    L%03d ... ", block_index[extable[i].startpc]);
+               printf("L%03d = ", block_index[extable[i].endpc]);
+               printf("L%03d\n", block_index[extable[i].handlerpc]);
+               }
+       
+       printf ("Local Table:\n");
+       for (i = 0; i < maxlocals; i++) {
+               printf("   %3d: ", i);
+               for (j = TYPE_INT; j <= TYPE_ADR; j++)
+                       if (locals[i][j].type >= 0) {
+                               printf("   (%d) ", j);
+                               if (locals[i][j].flags)
+                                       printf("m");
+                               else
+                                       printf("r");
+                               printf("%2d", locals[i][j].regoff);
+                               }
+               printf("\n");
+               }
+       printf("\n");
+
+       printf ("Interface Table:\n");
+       for (i = 0; i < maxstack; i++) {
+               if ((interfaces[i][0].type >= 0) || (interfaces[i][1].type >= 0) ||
+                   (interfaces[i][2].type >= 0) || (interfaces[i][3].type >= 0) ||
+                   (interfaces[i][4].type >= 0)) {
+                       printf("   %3d: ", i);
+                       for (j = TYPE_INT; j <= TYPE_ADR; j++)
+                               if (interfaces[i][j].type >= 0) {
+                                       printf("   (%d) ", j);
+                                       if (interfaces[i][j].flags & SAVEDVAR)
+                                               printf("s");
+                                       else
+                                               printf("t");
+                                       if (interfaces[i][j].flags & INMEMORY)
+                                               printf("m");
+                                       else
+                                               printf("r");
+                                       printf("%2d", interfaces[i][j].regoff);
+                                       }
+                       printf("\n");
+                       }
+               }
+       printf("\n");
+       for (b = 0; b < block_count; b++) {
+               deadcode = block[b].flags <= BBREACHED;
+               printf("[");
+               if (deadcode)
+                       for (j = maxstack; j > 0; j--)
+                               printf(" ?  ");
+               else
+                       print_stack(block[b].instack);
+               printf("] L%03d:\n", b);
+               for (i = block[b].ipc; i < block[b + 1].ipc; i++) {
+                       printf("[");
+                       if (deadcode) {
+                               for (j = maxstack; j > 0; j--)
+                                       printf(" ?  ");
+                               }
+                       else
+                               print_stack(instr[i].dst);
+                       printf("]     %4d  %s", i, icmd_names[instr[i].opc]);
+                       switch ((int) instr[i].opc) {
+                               case ICMD_IADDCONST:
+                               case ICMD_ISUBCONST:
+                               case ICMD_IMULCONST:
+                               case ICMD_IANDCONST:
+                               case ICMD_IORCONST:
+                               case ICMD_IXORCONST:
+                               case ICMD_ISHLCONST:
+                               case ICMD_ISHRCONST:
+                               case ICMD_IUSHRCONST:
+                               case ICMD_ICONST:
+                               case ICMD_GETFIELD:
+                               case ICMD_PUTFIELD:
+                                       printf(" %d", instr[i].val.i);
+                                       break;
+                               case ICMD_LADDCONST:
+                               case ICMD_LSUBCONST:
+                               case ICMD_LMULCONST:
+                               case ICMD_LANDCONST:
+                               case ICMD_LORCONST:
+                               case ICMD_LXORCONST:
+                               case ICMD_LSHLCONST:
+                               case ICMD_LSHRCONST:
+                               case ICMD_LUSHRCONST:
+                               case ICMD_LCONST:
+                                       printf(" %ld", instr[i].val.l);
+                                       break;
+                               case ICMD_FCONST:
+                                       printf(" %f", instr[i].val.f);
+                                       break;
+                               case ICMD_DCONST:
+                                       printf(" %f", instr[i].val.d);
+                                       break;
+                               case ICMD_ACONST:
+                               case ICMD_PUTSTATIC:
+                               case ICMD_GETSTATIC:
+                                       printf(" %p", instr[i].val.a);
+                                       break;
+                               case ICMD_IINC:
+                                       printf(" %d + %d", instr[i].op1, instr[i].val.i);
+                                       break;
+                               case ICMD_RET:
+                               case ICMD_ILOAD:
+                               case ICMD_LLOAD:
+                               case ICMD_FLOAD:
+                               case ICMD_DLOAD:
+                               case ICMD_ALOAD:
+                               case ICMD_ISTORE:
+                               case ICMD_LSTORE:
+                               case ICMD_FSTORE:
+                               case ICMD_DSTORE:
+                               case ICMD_ASTORE:
+                                       printf(" %d", instr[i].op1);
+                                       break;
+                               case ICMD_NEW:
+                                       printf(" ");
+                                       unicode_fprint(stdout,
+                                                      ((classinfo *) instr[i].val.a)->name);
+                                       break;
+                               case ICMD_NEWARRAY:
+                                       switch (instr[i].op1) {
+                                               case 4:
+                                                       printf(" boolean");
+                                                       break;
+                                               case 5:
+                                                       printf(" char");
+                                                       break;
+                                               case 6:
+                                                       printf(" float");
+                                                       break;
+                                               case 7:
+                                                       printf(" double");
+                                                       break;
+                                               case 8:
+                                                       printf(" byte");
+                                                       break;
+                                               case 9:
+                                                       printf(" short");
+                                                       break;
+                                               case 10:
+                                                       printf(" int");
+                                                       break;
+                                               case 11:
+                                                       printf(" long");
+                                                       break;
+                                               }
+                                       break;
+                               case ICMD_ANEWARRAY:
+                                       if (instr[i].op1) {
+                                               printf(" ");
+                                               unicode_fprint(stdout,
+                                                              ((classinfo *) instr[i].val.a)->name);
+                                               }
+                                       break;
+                               case ICMD_CHECKCAST:
+                               case ICMD_INSTANCEOF:
+                                       if (instr[i].op1) {
+                                               printf(" ");
+                                               unicode_fprint(stdout,
+                                                              ((classinfo *) instr[i].val.a)->name);
+                                               }
+                                       break;
+                               case ICMD_BUILTIN3:
+                               case ICMD_BUILTIN2:
+                               case ICMD_BUILTIN1:
+                                       printf(" %s", builtin_name((functionptr) instr[i].val.a));
+                                       break;
+                               case ICMD_INVOKEVIRTUAL:
+                               case ICMD_INVOKESPECIAL:
+                               case ICMD_INVOKESTATIC:
+                               case ICMD_INVOKEINTERFACE:
+                                       printf(" ");
+                                       unicode_fprint(stdout,
+                                                      ((methodinfo *) instr[i].val.a)->class->name);
+                                       printf(".");
+                                       unicode_fprint(stdout,
+                                                      ((methodinfo *) instr[i].val.a)->name);
+                                       break;
+                               case ICMD_IFEQ:
+                               case ICMD_IFNE:
+                               case ICMD_IFLT:
+                               case ICMD_IFGE:
+                               case ICMD_IFGT:
+                               case ICMD_IFLE:
+                               case ICMD_IF_LEQ:
+                               case ICMD_IF_LNE:
+                               case ICMD_IF_LLT:
+                               case ICMD_IF_LGE:
+                               case ICMD_IF_LGT:
+                               case ICMD_IF_LLE:
+                                       printf("(%d) L%03d", instr[i].val.i, block_index[instr[i].op1]);
+                                       break;
+                               case ICMD_JSR:
+                               case ICMD_GOTO:
+                               case ICMD_IFNULL:
+                               case ICMD_IFNONNULL:
+                               case ICMD_IF_ICMPEQ:
+                               case ICMD_IF_ICMPNE:
+                               case ICMD_IF_ICMPLT:
+                               case ICMD_IF_ICMPGE:
+                               case ICMD_IF_ICMPGT:
+                               case ICMD_IF_ICMPLE:
+                               case ICMD_IF_LCMPEQ:
+                               case ICMD_IF_LCMPNE:
+                               case ICMD_IF_LCMPLT:
+                               case ICMD_IF_LCMPGE:
+                               case ICMD_IF_LCMPGT:
+                               case ICMD_IF_LCMPLE:
+                               case ICMD_IF_ACMPEQ:
+                               case ICMD_IF_ACMPNE:
+                                       printf(" L%03d", block_index[instr[i].op1]);
+                                       break;
+                               case ICMD_TABLESWITCH:
+                                       s4ptr = instr[i].val.a;
+                                       printf(" L%03d;", block_index[*s4ptr++]); /* default */
+                                       j = *s4ptr++;                               /* low     */
+                                       j = *s4ptr++ - j;                           /* high    */
+                                       while (j >= 0) {
+                                               printf(" L%03d", block_index[*s4ptr++]);
+                                               j--;
+                                               }
+                                       break;
+                               case ICMD_LOOKUPSWITCH:
+                                       s4ptr = instr[i].val.a;
+                                       printf(" L%d", block_index[*s4ptr++]);   /* default */
+                                       j = *s4ptr++;                               /* count   */
+                                       while (--j >= 0) {
+                                               printf(" L%03d", block_index[s4ptr[1]]);
+                                               s4ptr += 2;
+                                               }
+                                       break;
+                               }
+                       printf("\n");
+                       }
+       }
+}
diff --git a/ncomp/ntools.c b/ncomp/ntools.c
new file mode 100644 (file)
index 0000000..ddedc43
--- /dev/null
@@ -0,0 +1,170 @@
+/***************************** ncomp/ntools.c **********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Ein paar zus"atzlich notwendige Funktionen, die sonst nirgends 
+       hinpassen.
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/03
+
+*******************************************************************************/
+
+
+/***************** Funktion: compiler_addinitclass ****************************
+
+       zum Eintragen einer Klasse in die Liste der noch zu initialisierenden 
+       Klassen
+       
+******************************************************************************/
+                                
+static void compiler_addinitclass (classinfo *c)
+{
+       classinfo *cl;
+
+       if (c->initialized) return;
+       
+       cl = chain_first(uninitializedclasses);
+       if (cl == c)
+               return;
+       
+       if (cl == class)
+               cl = chain_next(uninitializedclasses);
+       for (;;) {
+               if (cl == c)
+                       return;
+               if (cl == NULL) {
+                       if (runverbose) {
+                               sprintf(logtext, "compiler_addinitclass: ");
+                               unicode_sprint(logtext+strlen(logtext), c->name);
+                               dolog();
+                               }
+                       chain_addlast(uninitializedclasses, c);
+                       return;
+                       }
+               if (c < cl) {
+                       if (runverbose) {
+                               sprintf(logtext, "compiler_addinitclass: ");
+                               unicode_sprint(logtext+strlen(logtext), c->name);
+                               dolog();
+                               }
+                       chain_addbefore(uninitializedclasses, c);
+                       return;
+                       }
+               cl = chain_next(uninitializedclasses);
+               }
+}
+                                
+
+
+/***************** Hilfsfunktionen zum Decodieren des Bytecodes ***************
+
+       lesen ein Datum des gew"unschten Typs aus dem Bytecode an der
+       angegebenen Stelle
+
+******************************************************************************/
+
+#define code_get_u1(pos)    jcode[pos]
+#define code_get_s1(pos)    ((s1)jcode[pos])
+#define code_get_u2(pos)    ((((u2)jcode[pos])<<8)+jcode[pos+1])
+#define code_get_s2(pos)    ((s2)((((u2)jcode[pos])<<8)+jcode[pos+1]))
+#define code_get_u4(pos)    ((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
+                             (((u4)jcode[pos+2])<<8)+jcode[pos+3])
+#define code_get_s4(pos)    ((s4)((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
+                             (((u4)jcode[pos+2])<<8)+jcode[pos+3]))
+
+
+/******************** Funktion: descriptor2types *****************************
+
+       Decodiert einen Methoddescriptor.
+       Beim Aufruf dieser Funktion MUSS (!!!) der Descriptor ein
+       gueltiges Format haben (wird eh vorher vom loader ueberprueft).
+       
+       Die Funktion erzeugt ein Array von integers (u2), in das die 
+       Parametertypen eingetragen werden, und liefert einen Zeiger auf
+       das Array in einem Referenzparameter ('paramtypes') zur"uck.
+       Die L"ange dieses Arrays und der Methodenr"uckgabewert werden ebenfalls
+       in Referenzparametern zur"uckgeliefert.
+       
+       Der Parameter 'isstatic' gibt an (wenn true), dass kein zus"atzlicher
+       erster Eintrag f"ur den this-Zeiger in das Array eingetragen
+       werden soll (sonst wird er n"amlich automatisch erzeugt, mit dem
+       Typ TYPE_ADR).
+       
+******************************************************************************/                
+
+static void descriptor2types (methodinfo *m)
+{
+       u1 *types, *tptr;
+       int pcount, c;
+       u2 *cptr;
+
+       pcount = 0;
+       types = DMNEW (u1, m->descriptor->length);
+       
+       tptr = types;
+       if (!(m->flags & ACC_STATIC)) {
+               *tptr++ = TYPE_ADR;
+               pcount++;
+               }
+
+       cptr = m->descriptor->text;
+       cptr++;
+       while ((c = *cptr++) != ')') {
+               pcount++;
+               switch (c) {
+                       case 'B':
+                       case 'C':
+                       case 'I':
+                       case 'S':
+                       case 'Z':  *tptr++ = TYPE_INT;
+                                  break;
+                       case 'J':  *tptr++ = TYPE_LNG;
+                                  break;
+                       case 'F':  *tptr++ = TYPE_FLT;
+                                  break;
+                       case 'D':  *tptr++ = TYPE_DBL;
+                                  break;
+                       case 'L':  *tptr++ = TYPE_ADR;
+                                  while (*cptr++ != ';');
+                                  break;
+                       case '[':  *tptr++ = TYPE_ADR;
+                                  while (c == '[')
+                                      c = *cptr++;
+                                  if (c == 'L')
+                                      while (*cptr++ != ';') /* skip */;
+                                  break;
+                       default:   panic ("Ill formed methodtype-descriptor");
+                       }
+               }
+               
+       switch (*cptr) {
+               case 'B':
+               case 'C':
+               case 'I':
+               case 'S':
+               case 'Z':  m->returntype = TYPE_INT;
+                          break;
+               case 'J':  m->returntype = TYPE_LNG;
+                          break;
+               case 'F':  m->returntype = TYPE_FLT;
+                          break;
+               case 'D':  m->returntype = TYPE_DBL;
+                          break;
+               case '[':
+               case 'L':  m->returntype = TYPE_ADR;
+                          break;
+               case 'V':  m->returntype = TYPE_VOID;
+                          break;
+       
+               default:   panic ("Ill formed methodtype-descriptor");
+               }
+
+       m->paramcount = pcount;
+       m->paramtypes = types;
+}
+
diff --git a/newcomp.c b/newcomp.c
new file mode 100644 (file)
index 0000000..dad1476
--- /dev/null
+++ b/newcomp.c
@@ -0,0 +1,437 @@
+/***************************** ncomp/ncomp.c ***********************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties.
+
+       Contains the functions which translates a JavaVM method into native code.
+       This is the new version of the compiler which is a lot faster and has new
+       exception handling schemes. The main function is new_comp.
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/05
+
+*******************************************************************************/
+
+#include "signal.h"
+#include "global.h"
+#include "ncomp/ncomp.h"
+
+#include "loader.h"
+#include "tables.h"
+#include "builtin.h"
+#include "native.h"
+#include "asmpart.h"
+
+#include "threads/thread.h"
+
+
+/*************************** global switches **********************************/
+
+bool compileverbose = false;
+bool showstack = false;
+bool showdisassemble = false; 
+bool showintermediate = false;
+int  optimizelevel = 0;
+
+bool checkbounds = true;
+bool checknull = true;
+bool checkfloats = true;
+bool checksync = true;
+
+bool getcompilingtime = false;
+long compilingtime = 0;
+
+int  has_ext_instr_set = 0;
+
+bool statistics = false;         
+
+int count_jit_calls = 0;
+int count_methods = 0;
+int count_spills = 0;
+int count_pcmd_activ = 0;
+int count_pcmd_drop = 0;
+int count_pcmd_zero = 0;
+int count_pcmd_const_store = 0;
+int count_pcmd_const_alu = 0;
+int count_pcmd_const_bra = 0;
+int count_pcmd_load = 0;
+int count_pcmd_move = 0;
+int count_load_instruction = 0;
+int count_pcmd_store = 0;
+int count_pcmd_store_comb = 0;
+int count_dup_instruction = 0;
+int count_pcmd_op = 0;
+int count_pcmd_mem = 0;
+int count_pcmd_met = 0;
+int count_pcmd_bra = 0;
+int count_pcmd_table = 0;
+int count_pcmd_return = 0;
+int count_pcmd_returnx = 0;
+int count_check_null = 0;
+int count_check_bound = 0;
+int count_max_basic_blocks = 0;
+int count_basic_blocks = 0;
+int count_javainstr = 0;
+int count_max_javainstr = 0;
+int count_javacodesize = 0;
+int count_javaexcsize = 0;
+int count_calls = 0;
+int count_tryblocks = 0;
+int count_code_len = 0;
+int count_data_len = 0;
+int count_cstub_len = 0;
+int count_nstub_len = 0;
+int count_max_new_stack = 0;
+int count_upper_bound_new_stack = 0;
+static int count_block_stack_init[11] = {0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0};
+int *count_block_stack = count_block_stack_init;
+static int count_analyse_iterations_init[5] = {0, 0, 0, 0, 0};
+int *count_analyse_iterations = count_analyse_iterations_init;
+static int count_method_bb_distribution_init[9] = {0, 0, 0, 0, 0,  0, 0, 0, 0};
+int *count_method_bb_distribution = count_method_bb_distribution_init;
+static int count_block_size_distribution_init[18] = {0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0,   0, 0, 0, 0, 0,   0, 0, 0};
+int *count_block_size_distribution = count_block_size_distribution_init;
+static int count_store_length_init[21] = {0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
+                                          0, 0, 0, 0, 0,  0, 0, 0, 0, 0,  0};
+int *count_store_length = count_store_length_init;
+static int count_store_depth_init[11] = {0, 0, 0, 0, 0,  0, 0, 0, 0, 0,   0};
+int *count_store_depth = count_store_depth_init;
+
+
+/*********************** include compiler data types **************************/ 
+
+#include "ncomp/ncompdef.h"
+
+
+/*********************** global compiler variables ****************************/
+
+                                /* data about the currently compiled method   */
+
+static classinfo  *class;       /* class the compiled method belongs to       */
+static methodinfo *method;      /* pointer to method info of compiled method  */
+static unicode    *descriptor;  /* type descriptor of compiled method         */
+static u2         mparamcount;  /* number of parameters (incl. this)          */
+static u1         *mparamtypes; /* types of all parameters (TYPE_INT, ...)    */
+static u2         mreturntype;  /* return type of method                      */
+       
+static int maxstack;            /* maximal JavaVM stack size                  */
+static int maxlocals;           /* maximal number of local JavaVM variables   */
+static int jcodelength;         /* length of JavaVM-codes                     */
+static u1 *jcode;               /* pointer to start of JavaVM-code            */
+static int exceptiontablelength;/* length of exception table                  */
+static exceptiontable *extable; /* pointer to start of exception table        */
+
+static int block_count;         /* number of basic blocks                     */
+static basicblock *block;       /* points to basic block array                */
+static int *block_index;        /* a table which contains for every byte of   */
+                                /* JavaVM code a basic block index if at this */
+                                /* byte there is the start of a basic block   */
+
+static int instr_count;         /* number of JavaVM instructions              */
+static instruction *instr;      /* points to intermediate code instructions   */
+
+static int stack_count;         /* number of stack elements                   */
+static stackelement *stack;     /* points to intermediate code instructions   */
+
+static bool isleafmethod;       /* true if a method doesn't call subroutines  */
+
+/* list of all classes used by the compiled method which have to be           */
+/* initialised (if not already done) before execution of this method          */
+
+static chain *uninitializedclasses;  
+                                
+
+/******************** include compiler subsystems *****************************/
+
+#include "sysdep/ngen.h"        /* code generator header file                 */ 
+#include "ncomp/ntools.c"       /* compiler tool functions                    */ 
+#include "ncomp/mcode.c"        /* code generation tool functions             */ 
+#include "ncomp/nparse.c"       /* parsing of JavaVM code                     */ 
+#include "ncomp/nreg.c"         /* register allocation and support routines   */ 
+#include "ncomp/nstack.c"       /* analysing the stack operations             */ 
+#include "sysdep/ngen.c"        /* code generator                             */ 
+#include "sysdep/disass.c"      /* disassembler (for debug purposes only)     */ 
+
+
+
+
+/* dummy function, used when there is no JavaVM code available                */
+
+static void* do_nothing_function() 
+{
+       return NULL;
+}
+
+
+/*******************************************************************************
+
+       new_compile, new version of compiler, translates one method to machine code
+
+*******************************************************************************/
+
+methodptr new_compile(methodinfo *m)
+{
+       int  dumpsize;
+       long starttime = 0;
+       long stoptime  = 0;
+
+       /* if method has been already compiled return immediately */
+
+       count_jit_calls++;
+
+       if (m->entrypoint)
+               return m->entrypoint;
+
+       count_methods++;
+
+       intsDisable();      /* disable interrupts */
+       
+
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size ();
+
+       /* measure time */
+
+       if (getcompilingtime)
+               starttime = getcputime();
+
+       /* if there is no javacode print error message and return empty method    */
+
+       if (! m->jcode) {
+               sprintf(logtext, "No code given for: ");
+               unicode_sprint(logtext+strlen(logtext), m->class->name);
+               strcpy(logtext+strlen(logtext), ".");
+               unicode_sprint(logtext+strlen(logtext), m->name);
+               unicode_sprint(logtext+strlen(logtext), m->descriptor);
+               dolog();
+               intsRestore();                             /* enable interrupts again */
+               return (methodptr) do_nothing_function;    /* return empty method     */
+               }
+
+       /* print log message for compiled method */
+
+       if (compileverbose) {
+               sprintf(logtext, "Compiling: ");
+               unicode_sprint(logtext+strlen(logtext), m->class->name);
+               strcpy(logtext+strlen(logtext), ".");
+               unicode_sprint(logtext+strlen(logtext), m->name);
+               unicode_sprint(logtext+strlen(logtext), m->descriptor);
+               dolog ();
+               }
+
+
+       /* initialisation of variables and subsystems */
+
+       isleafmethod = true;
+
+       method = m;
+       class = m->class;
+       descriptor = m->descriptor;
+       maxstack = m->maxstack;
+       maxlocals = m->maxlocals;
+       jcodelength = m->jcodelength;
+       jcode = m->jcode;
+       exceptiontablelength = m->exceptiontablelength;
+       extable = m->exceptiontable;
+
+#ifdef STATISTICS
+       count_tryblocks += exceptiontablelength;
+       count_javacodesize += jcodelength + 18;
+       count_javaexcsize += exceptiontablelength * 8;
+#endif
+
+       /* initialise parameter type descriptor */
+
+       descriptor2types (m);
+       mreturntype = m->returntype;
+       mparamcount = m->paramcount;
+       mparamtypes = m->paramtypes;
+
+       /* initialize class list with class the compiled method belongs to */
+
+       uninitializedclasses = chain_new(); 
+       compiler_addinitclass (m->class);
+
+
+       /********************** call the compiler passes **************************/
+       
+       reg_init();
+       local_init();
+       mcode_init();
+
+       if (runverbose)
+               allocate_literals();
+
+       parse();
+
+       analyse_stack();
+
+       interface_regalloc();
+
+       allocate_scratch_registers();
+       
+       local_regalloc();
+       
+       gen_mcode();
+
+       
+       /*********** Zwischendarstellungen auf Wunsch ausgeben **********/
+               
+       if (showintermediate)
+               show_icmd_method();
+
+       if (showdisassemble) {
+               dseg_display((void*) (m->mcode));
+               disassemble((void*) (m->mcode + dseglen), m->mcodelength - dseglen);
+               fflush(stdout);
+               }
+
+
+       /* release dump area */
+
+       dump_release (dumpsize);
+
+       /* measure time */
+
+       if (getcompilingtime) {
+               stoptime = getcputime();
+               compilingtime += (stoptime-starttime); 
+               }
+
+       /* initialize all used classes */
+       /* because of reentrant code global variables are not allowed here        */
+
+       {
+       chain *ul = uninitializedclasses;   /* list of uninitialized classes      */ 
+       classinfo *c;                       /* single class                       */
+
+       while ((c = chain_first(ul)) != NULL) {
+               chain_remove (ul);
+               class_init (c);                         /* may again call the compiler        */
+               }
+       chain_free (ul);
+       }
+
+       intsRestore();    /* enable interrupts again */
+
+       /* return pointer to the methods entry point */
+       
+       return m -> entrypoint;
+}
+
+
+/************ functions for compiler initialisation and finalisation **********/
+
+void ncomp_init ()
+{
+       int i;
+
+       has_ext_instr_set = ! has_no_x_instr_set();
+
+       for (i = 0; i < 256; i++)
+               stackreq[i] = 1;
+
+       stackreq[JAVA_NOP]          = 0;
+       stackreq[JAVA_ISTORE]       = 0;
+       stackreq[JAVA_LSTORE]       = 0;
+       stackreq[JAVA_FSTORE]       = 0;
+       stackreq[JAVA_DSTORE]       = 0;
+       stackreq[JAVA_ASTORE]       = 0;
+       stackreq[JAVA_ISTORE_0]     = 0;
+       stackreq[JAVA_ISTORE_1]     = 0;
+       stackreq[JAVA_ISTORE_2]     = 0;
+       stackreq[JAVA_ISTORE_3]     = 0;
+       stackreq[JAVA_LSTORE_0]     = 0;
+       stackreq[JAVA_LSTORE_1]     = 0;
+       stackreq[JAVA_LSTORE_2]     = 0;
+       stackreq[JAVA_LSTORE_3]     = 0;
+       stackreq[JAVA_FSTORE_0]     = 0;
+       stackreq[JAVA_FSTORE_1]     = 0;
+       stackreq[JAVA_FSTORE_2]     = 0;
+       stackreq[JAVA_FSTORE_3]     = 0;
+       stackreq[JAVA_DSTORE_0]     = 0;
+       stackreq[JAVA_DSTORE_1]     = 0;
+       stackreq[JAVA_DSTORE_2]     = 0;
+       stackreq[JAVA_DSTORE_3]     = 0;
+       stackreq[JAVA_ASTORE_0]     = 0;
+       stackreq[JAVA_ASTORE_1]     = 0;
+       stackreq[JAVA_ASTORE_2]     = 0;
+       stackreq[JAVA_ASTORE_3]     = 0;
+       stackreq[JAVA_IASTORE]      = 0;
+       stackreq[JAVA_LASTORE]      = 0;
+       stackreq[JAVA_FASTORE]      = 0;
+       stackreq[JAVA_DASTORE]      = 0;
+       stackreq[JAVA_AASTORE]      = 0;
+       stackreq[JAVA_BASTORE]      = 0;
+       stackreq[JAVA_CASTORE]      = 0;
+       stackreq[JAVA_SASTORE]      = 0;
+       stackreq[JAVA_POP]          = 0;
+       stackreq[JAVA_POP2]         = 0;
+       stackreq[JAVA_IINC]         = 0;
+       stackreq[JAVA_IFEQ]         = 0;
+       stackreq[JAVA_IFNE]         = 0;
+       stackreq[JAVA_IFLT]         = 0;
+       stackreq[JAVA_IFGE]         = 0;
+       stackreq[JAVA_IFGT]         = 0;
+       stackreq[JAVA_IFLE]         = 0;
+       stackreq[JAVA_IF_ICMPEQ]    = 0;
+       stackreq[JAVA_IF_ICMPNE]    = 0;
+       stackreq[JAVA_IF_ICMPLT]    = 0;
+       stackreq[JAVA_IF_ICMPGE]    = 0;
+       stackreq[JAVA_IF_ICMPGT]    = 0;
+       stackreq[JAVA_IF_ICMPLE]    = 0;
+       stackreq[JAVA_IF_ACMPEQ]    = 0;
+       stackreq[JAVA_IF_ACMPNE]    = 0;
+       stackreq[JAVA_GOTO]         = 0;
+       stackreq[JAVA_RET]          = 0;
+       stackreq[JAVA_TABLESWITCH]  = 0;
+       stackreq[ICMD_LOOKUPSWITCH] = 0;
+       stackreq[JAVA_IRETURN]      = 0;
+       stackreq[JAVA_LRETURN]      = 0;
+       stackreq[JAVA_FRETURN]      = 0;
+       stackreq[JAVA_DRETURN]      = 0;
+       stackreq[JAVA_ARETURN]      = 0;
+       stackreq[JAVA_RETURN]       = 0;
+       stackreq[JAVA_PUTSTATIC]    = 0;
+       stackreq[JAVA_PUTFIELD]     = 0;
+       stackreq[JAVA_MONITORENTER] = 0;
+       stackreq[ICMD_MONITOREXIT]  = 0;
+       stackreq[JAVA_WIDE]         = 0;
+       stackreq[JAVA_IFNULL]       = 0;
+       stackreq[JAVA_IFNONNULL]    = 0;
+       stackreq[JAVA_GOTO_W]       = 0;
+       stackreq[JAVA_BREAKPOINT]   = 0;
+
+       stackreq[JAVA_SWAP] = 2;
+       stackreq[JAVA_DUP2] = 2;
+       stackreq[JAVA_DUP_X1] = 3;
+       stackreq[JAVA_DUP_X2] = 4;
+       stackreq[JAVA_DUP2_X1] = 3;
+       stackreq[JAVA_DUP2_X2] = 4;
+       
+       for (i = 0; i < 256; i++) stdopdescriptors[i] = NULL;
+
+       for (i = 0; i < sizeof(stdopdescriptortable)/sizeof(stdopdescriptor); i++) {
+               
+               if (stdopdescriptortable[i].isfloat && checkfloats) {
+                       stdopdescriptortable[i].supported = false;
+                       }
+
+               stdopdescriptors[stdopdescriptortable[i].opcode] = 
+                  &(stdopdescriptortable[i]);
+               }
+
+       init_exceptions();
+}
+
+
+void ncomp_close()
+{
+/*     mcode_close(); */
+}
+
diff --git a/src/cacao/cacao.c b/src/cacao/cacao.c
new file mode 100644 (file)
index 0000000..d91cfc8
--- /dev/null
@@ -0,0 +1,750 @@
+/******************************* main.c ****************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enthaelt die Funktion main() und die Variablen fuer die 
+       globalen Optionen.
+       Dieser Modul erledigt folgende Aufgaben:
+          - Bearbeiten der command-line-options
+          - Aufrufen aller Initialisierungsroutinen
+          - Aufrufen des Classloaders
+          - Starten der main - Methode
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Andi Krall          EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/29
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "compiler.h"
+#include "ncomp/ncomp.h"
+#include "loader.h"
+
+#include "asmpart.h"
+#include "builtin.h"
+#include "native.h"
+
+#include "threads/thread.h"            /* schani */
+
+bool compileall = false;
+int  newcompiler = true;               
+bool verbose =  false;
+
+#ifndef USE_THREADS
+void **stackbottom = 0;
+#endif
+
+
+/********************* interne Funktion: get_opt *****************************
+       
+       liest die n"achste Option aus der Kommandozeile
+       
+******************************************************************************/
+
+#define OPT_DONE  -1
+#define OPT_ERROR  0
+#define OPT_IGNORE 1
+
+#define OPT_CLASSPATH   2
+#define OPT_D           3  
+#define OPT_MS          4  
+#define OPT_MX          5  
+#define OPT_VERBOSE1    6  
+#define OPT_VERBOSE     7  
+#define OPT_VERBOSEGC   8         
+#define OPT_VERBOSECALL 9          
+#define OPT_IEEE        10
+#define OPT_SOFTNULL    11
+#define OPT_TIME        12
+#define OPT_STAT        13
+#define OPT_LOG         14  
+#define OPT_CHECK       15
+#define OPT_LOAD        16  
+#define OPT_METHOD      17  
+#define OPT_SIGNATURE   18  
+#define OPT_SHOW        19 
+#define OPT_ALL         20 
+#define OPT_OLD         21 
+
+struct { char *name; bool arg; int value; } opts[] = {
+  { "classpath",   true,   OPT_CLASSPATH },
+  { "D",           true,   OPT_D },
+  { "ms",          true,   OPT_MS },
+  { "mx",          true,   OPT_MX },
+  { "noasyncgc",   false,  OPT_IGNORE },  
+  { "noverify",    false,  OPT_IGNORE },  
+  { "oss",         true,   OPT_IGNORE },  
+  { "ss",          true,   OPT_IGNORE },  
+  { "v",           false,  OPT_VERBOSE1 },
+  { "verbose",     false,  OPT_VERBOSE },
+  { "verbosegc",   false,  OPT_VERBOSEGC },
+  { "verbosecall", false,  OPT_VERBOSECALL },
+  { "ieee",        false,  OPT_IEEE },
+  { "softnull",    false,  OPT_SOFTNULL },
+  { "time",        false,  OPT_TIME },
+  { "stat",        false,  OPT_STAT },
+  { "log",         true,   OPT_LOG },
+  { "c",           true,   OPT_CHECK },
+  { "l",           false,  OPT_LOAD },
+  { "m",           true,   OPT_METHOD },
+  { "sig",         true,   OPT_SIGNATURE },
+  { "s",           true,   OPT_SHOW },          
+  { "all",         false,  OPT_ALL },          
+  { "old",         false,  OPT_OLD },          
+  { NULL,  false, 0 }
+};
+
+static int opt_ind = 1;
+static char *opt_arg;
+
+static int get_opt (int argc, char **argv) 
+{
+       char *a;
+       int i;
+       
+       if (opt_ind >= argc) return OPT_DONE;
+       
+       a = argv[opt_ind];
+       if (a[0] != '-') return OPT_DONE;
+
+       for (i=0; opts[i].name; i++) {
+               if (! opts[i].arg) {
+                       if (strcmp(a+1, opts[i].name) == 0) {  /* boolean option found */
+                               opt_ind++;
+                               return opts[i].value;
+                               }
+                       }
+               else {
+                       if (strcmp(a+1, opts[i].name) == 0) { /* parameter option found */
+                               opt_ind++;
+                               if (opt_ind < argc) {
+                                       opt_arg = argv[opt_ind];
+                                       opt_ind++;
+                                       return opts[i].value;
+                                       }
+                               return OPT_ERROR;
+                               }
+                       else {
+                               size_t l = strlen(opts[i].name);
+                               if (strlen(a+1) > l) {
+                                       if (memcmp (a+1, opts[i].name, l)==0) {
+                                               opt_ind++;
+                                               opt_arg = a+1+l;
+                                               return opts[i].value;
+                                               }
+                                       }
+                               }
+                       }
+               } /* end for */ 
+
+       return OPT_ERROR;
+}
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JavaVM-Compilers auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+       printf ("USAGE: cacao [options] classname [program arguments\n");
+       printf ("Options:\n");
+       printf ("          -classpath path ...... specify a path to look for classes\n");
+       printf ("          -Dpropertyname=value . add an entry to the property list\n");
+       printf ("          -mx maxmem[k|m] ...... specify the size for the heap\n");
+       printf ("          -ms initmem[k|m] ..... specify the initial size for the heap\n");
+       printf ("          -v ................... write state-information\n");
+       printf ("          -verbose ............. write more information\n");
+       printf ("          -verbosegc ........... write message for each GC\n");
+       printf ("          -verbosecall ......... write message for each call\n");
+       printf ("          -ieee ................ use ieee compliant arithmetic\n");
+       printf ("          -softnull ............ use software nullpointer check\n");
+       printf ("          -time ................ measure the runtime\n");
+       printf ("          -stat ................ detailed compiler statistics\n");
+       printf ("          -log logfile ......... specify a name for the logfile\n");
+       printf ("          -c(heck) b(ounds...... don't check array bounds\n");
+       printf ("                   s(ync) ...... don't check for synchronization\n");
+       printf ("          -l ................... don't start the class after loading\n");
+       printf ("          -all ................. compile all methods, no execution\n");
+       printf ("          -old ................. use old JIT compiler\n");
+       printf ("          -m ................... compile only a specific method\n");
+       printf ("          -sig ................. specify signature for a specific method\n");
+       printf ("          -s(how)m(ethods) ..... show all methods&fields of a class\n");
+       printf ("                 c(onstants) ... show the constant pool\n");
+       printf ("                 a(ssembler) ... show disassembled listing\n");
+       printf ("                 s(tack) ....... show stack for every javaVM-command\n");
+       printf ("                 i(ntermediate). show intermediate representation\n");
+       printf ("                 u(nicode) ..... show the unicode - hash\n");
+}   
+
+
+
+/***************************** Funktion: print_times *********************
+
+       gibt eine Aufstellung der verwendeten CPU-Zeit aus
+
+**************************************************************************/
+
+static void print_times()
+{
+       long int totaltime = getcputime();
+       long int runtime = totaltime - loadingtime - compilingtime;
+
+       sprintf (logtext, "Time for loading classes: %ld secs, %ld millis",
+            loadingtime / 1000000, (loadingtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Time for compiling code:  %ld secs, %ld millis",
+            compilingtime / 1000000, (compilingtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Time for running program: %ld secs, %ld millis",
+            runtime / 1000000, (runtime % 1000000) / 1000);
+       dolog();
+       sprintf (logtext, "Total time: %ld secs, %ld millis",
+            totaltime / 1000000, (totaltime % 1000000) / 1000);
+       dolog();
+}
+
+
+
+
+
+
+/***************************** Funktion: print_stats *********************
+
+       outputs detailed compiler statistics
+
+**************************************************************************/
+
+static void print_stats()
+{
+       sprintf (logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
+       dolog();
+       sprintf (logtext, "Number of compiled Methods: %d", count_methods);
+       dolog();
+       sprintf (logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
+       dolog();
+       sprintf (logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
+       dolog();
+       sprintf (logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
+       dolog();
+       sprintf (logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
+       dolog();
+       sprintf (logtext, "Size of compiled JavaVM-Instructions:   %d(%d)", count_javacodesize,
+                                                     count_javacodesize - count_methods * 18);
+       dolog();
+       sprintf (logtext, "Size of compiled Exception Tables:      %d", count_javaexcsize);
+       dolog();
+       sprintf (logtext, "Value of extended instruction set var:  %d", has_ext_instr_set);
+       dolog();
+       sprintf (logtext, "Number of Alpha-Instructions: %d", count_code_len >> 2);
+       dolog();
+       sprintf (logtext, "Number of Spills: %d", count_spills);
+       dolog();
+       sprintf (logtext, "Number of Activ    Pseudocommands: %5d", count_pcmd_activ);
+       dolog();
+       sprintf (logtext, "Number of Drop     Pseudocommands: %5d", count_pcmd_drop);
+       dolog();
+       sprintf (logtext, "Number of Const    Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
+       dolog();
+       sprintf (logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+       dolog();
+       sprintf (logtext, "Number of Move     Pseudocommands: %5d", count_pcmd_move);
+       dolog();
+       sprintf (logtext, "Number of Load     Pseudocommands: %5d", count_load_instruction);
+       dolog();
+       sprintf (logtext, "Number of Store    Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+       dolog();
+       sprintf (logtext, "Number of OP       Pseudocommands: %5d", count_pcmd_op);
+       dolog();
+       sprintf (logtext, "Number of DUP      Pseudocommands: %5d", count_dup_instruction);
+       dolog();
+       sprintf (logtext, "Number of Mem      Pseudocommands: %5d", count_pcmd_mem);
+       dolog();
+       sprintf (logtext, "Number of Method   Pseudocommands: %5d", count_pcmd_met);
+       dolog();
+       sprintf (logtext, "Number of Branch   Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
+                         count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+       dolog();
+       sprintf (logtext, "Number of Table    Pseudocommands: %5d", count_pcmd_table);
+       dolog();
+       sprintf (logtext, "Number of Useful   Pseudocommands: %5d", count_pcmd_table +
+                count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+       dolog();
+       sprintf (logtext, "Number of Null Pointer Checks:     %5d", count_check_null);
+       dolog();
+       sprintf (logtext, "Number of Array Bound Checks:      %5d", count_check_bound);
+       dolog();
+       sprintf (logtext, "Number of Try-Blocks: %d", count_tryblocks);
+       dolog();
+       sprintf (logtext, "Maximal count of stack elements:   %d", count_max_new_stack);
+       dolog();
+       sprintf (logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+       dolog();
+       sprintf (logtext, "Distribution of stack sizes at block boundary");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
+               count_block_stack[1],count_block_stack[2],count_block_stack[3],count_block_stack[4],
+               count_block_stack[5],count_block_stack[6],count_block_stack[7],count_block_stack[8],
+               count_block_stack[9],count_block_stack[10]);
+       dolog();
+       sprintf (logtext, "Distribution of store stack depth");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9    >=10");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
+               count_store_depth[1],count_store_depth[2],count_store_depth[3],count_store_depth[4],
+               count_store_depth[5],count_store_depth[6],count_store_depth[7],count_store_depth[8],
+               count_store_depth[9],count_store_depth[10]);
+       dolog();
+       sprintf (logtext, "Distribution of store creator chains first part");
+       dolog();
+       sprintf (logtext, "    0    1    2    3    4    5    6    7    8    9  ");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
+               count_store_length[1],count_store_length[2],count_store_length[3],count_store_length[4],
+               count_store_length[5],count_store_length[6],count_store_length[7],count_store_length[8],
+               count_store_length[9]);
+       dolog();
+       sprintf (logtext, "Distribution of store creator chains second part");
+       dolog();
+       sprintf (logtext, "   10   11   12   13   14   15   16   17   18   19  >=20");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
+               count_store_length[11],count_store_length[12],count_store_length[13],count_store_length[14],
+               count_store_length[15],count_store_length[16],count_store_length[17],count_store_length[18],
+               count_store_length[19],count_store_length[20]);
+       dolog();
+       sprintf (logtext, "Distribution of analysis iterations");
+       dolog();
+       sprintf (logtext, "    1    2    3    4    >=5");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0],count_analyse_iterations[1],
+               count_analyse_iterations[2],count_analyse_iterations[3],count_analyse_iterations[4]);
+       dolog();
+       sprintf (logtext, "Distribution of basic blocks per method");
+       dolog();
+       sprintf (logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75  >75");
+       dolog();
+       sprintf (logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
+               count_method_bb_distribution[1],count_method_bb_distribution[2],count_method_bb_distribution[3],
+               count_method_bb_distribution[4],count_method_bb_distribution[5],count_method_bb_distribution[6],
+               count_method_bb_distribution[7],count_method_bb_distribution[8]);
+       dolog();
+       sprintf (logtext, "Distribution of basic block sizes");
+       dolog();
+       sprintf (logtext,
+       "  1    2    3    4   5   6   7   8   9  10 <13 <15 <17 <19 <21 <26 <31 >30");
+       dolog();
+       sprintf (logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
+               count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
+               count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
+               count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
+               count_block_size_distribution[9], count_block_size_distribution[10],count_block_size_distribution[11],
+               count_block_size_distribution[12],count_block_size_distribution[13],count_block_size_distribution[14],
+               count_block_size_distribution[15],count_block_size_distribution[16],count_block_size_distribution[17]);
+       dolog();
+       sprintf (logtext, "Size of Code Area (Kb):  %10.3f", (float) count_code_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of data Area (Kb):  %10.3f", (float) count_data_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
+       dolog();
+       sprintf (logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_unicode_len) / 1024);
+       dolog();
+       sprintf (logtext, "Size of Vftbl (Kb):      %10.3f", (float) count_vftbl_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of comp stub (Kb):  %10.3f", (float) count_cstub_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of Unicode (Kb):    %10.3f", (float) count_unicode_len / 1024);
+       dolog();
+       sprintf (logtext, "Size of VMCode (Kb):     %10.3f(%d)", (float) count_vmcode_len / 1024,
+                                                     count_vmcode_len - 18 * count_all_methods);
+       dolog();
+       sprintf (logtext, "Size of ExTable (Kb):    %10.3f", (float) count_extable_len / 1024);
+       dolog();
+       sprintf (logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
+       dolog();
+}
+
+
+/********** Funktion: class_compile_methods   (nur f"ur Debug-Zwecke) ********/
+
+void class_compile_methods ()
+{
+       int        i;
+       classinfo  *c;
+       methodinfo *m;
+       
+       c = list_first (&linkedclasses);
+       while (c) {
+               for (i = 0; i < c -> methodscount; i++) {
+                       m = &(c->methods[i]);
+                       if (m->jcode) {
+                               if (newcompiler)
+                                       (void) new_compile(m);
+                               else
+                                       (void) compiler_compile(m);
+                               }
+                       }
+               c = list_next (&linkedclasses, c);
+               }
+}
+
+
+/************************** Funktion: main *******************************
+
+   Das Hauptprogramm.
+   Wird vom System zu Programstart aufgerufen (eh klar).
+   
+**************************************************************************/
+
+
+int main(int argc, char **argv)
+{
+       s4 i,j;
+       char *cp;
+       classinfo *topclass;
+       java_objectheader *exceptionptr;
+       void *dummy;
+       
+
+   /********** interne (nur fuer main relevante Optionen) **************/
+   
+       char logfilename[200] = "";
+       u4 heapsize = 16000000;
+       u4 heapstartsize = 200000;
+       char classpath[500] = ".:/usr/local/lib/java/classes";
+       bool showmethods = false;
+       bool showconstantpool = false;
+       bool showunicode = false;
+       bool startit = true;
+       char *specificmethodname = NULL;
+       char *specificsignature = NULL;
+
+#ifndef USE_THREADS
+       stackbottom = &dummy;
+#endif
+
+
+   /************ Infos aus der Environment lesen ************************/
+
+       cp = getenv ("CLASSPATH");
+       if (cp) {
+               strcpy (classpath, cp);
+               }
+
+   /***************** Interpretieren der Kommandozeile *****************/
+   
+   checknull = false;
+   checkfloats = false;
+
+       while ( (i = get_opt(argc,argv)) != OPT_DONE) {
+
+               switch (i) {
+                       case OPT_IGNORE: break;
+                       
+                       case OPT_CLASSPATH:    
+                               strcpy (classpath + strlen(classpath), ":");
+                               strcpy (classpath + strlen(classpath), opt_arg);
+                               break;
+                               
+                       case OPT_D:
+                               {
+                               int n,l=strlen(opt_arg);
+                               for (n=0; n<l; n++) {
+                                       if (opt_arg[n]=='=') {
+                                               opt_arg[n] = '\0';
+                                               attach_property (opt_arg, opt_arg+n+1);
+                                               goto didit;
+                                               }
+                                       }
+                               print_usage();
+                               exit(10);
+                                       
+                               didit: ;
+                               }       
+                               break;
+                               
+                       case OPT_MS:
+                       case OPT_MX:
+                               if (opt_arg[strlen(opt_arg)-1] == 'k') {
+                                       j = 1024 * atoi(opt_arg);
+                                       }
+                               else if (opt_arg[strlen(opt_arg)-1] == 'm') {
+                                       j = 1024 * 1024 * atoi(opt_arg);
+                                       }
+                               else j = atoi(opt_arg);
+                               
+                               if (i==OPT_MX) heapsize = j;
+                               else heapstartsize = j;
+                               break;
+
+                       case OPT_VERBOSE1:
+                               verbose = true;
+                               break;
+                                                               
+                       case OPT_VERBOSE:
+                               verbose = true;
+                               loadverbose = true;
+                               initverbose = true;
+                               compileverbose = true;
+                               break;
+                               
+                       case OPT_VERBOSEGC:
+                               collectverbose = true;
+                               break;
+                               
+                       case OPT_VERBOSECALL:
+                               runverbose = true;
+                               break;
+                               
+                       case OPT_IEEE:
+                               checkfloats = true;
+                               break;
+
+                       case OPT_SOFTNULL:
+                               checknull = true;
+                               break;
+
+                       case OPT_TIME:
+                               getcompilingtime = true;
+                               getloadingtime = true;
+                               break;
+                                       
+                       case OPT_STAT:
+                               statistics = true;
+                               break;
+                                       
+                       case OPT_LOG:
+                               strcpy (logfilename, opt_arg);
+                               break;
+                       
+                       
+                       case OPT_CHECK:
+                       for (j=0; j<strlen(opt_arg); j++) {
+                               switch (opt_arg[j]) {
+                               case 'b': checkbounds=false; break;
+                                       case 's': checksync=false; break;
+                               default:  print_usage();
+                                         exit(10);
+                               }
+                               }
+                       break;
+                       
+                       case OPT_LOAD:
+                               startit = false;
+                               makeinitializations = false;
+                               break;
+
+                       case OPT_METHOD:
+                               startit = false;
+                               specificmethodname = opt_arg;                   
+                               makeinitializations = false;
+                       break;
+                       
+                       case OPT_SIGNATURE:
+                               specificsignature = opt_arg;                    
+                       break;
+                       
+                       case OPT_ALL:
+                               compileall = true;              
+                               startit = false;
+                               makeinitializations = false;
+                       break;
+                       
+                       case OPT_OLD:
+                               newcompiler = false;                    
+                               checknull = true;
+                       break;
+                       
+               case OPT_SHOW:       /* Anzeigeoptionen */
+                       for (j=0; j<strlen(opt_arg); j++) {             
+                               switch (opt_arg[j]) {
+                               case 'm':  showmethods=true; break;
+                               case 'c':  showconstantpool=true; break;
+                               case 'a':  showdisassemble=true; compileverbose=true; break;
+                               case 's':  showstack=true; compileverbose=true; break;
+                               case 'i':  showintermediate=true; compileverbose=true; break;
+                               case 'u':  showunicode=true; break;
+                               default:   print_usage();
+                                      exit(10);
+                               }
+                               }
+                       break;
+                       
+                       default:
+                               print_usage();
+                               exit(10);
+                       }
+                       
+                       
+               }
+   
+   
+       if (opt_ind >= argc) {
+               print_usage ();
+               exit(10);
+               }
+
+
+   /**************************** Programmstart *****************************/
+
+       log_init (logfilename);
+       if (verbose) {
+               log_text (
+               "CACAO started -------------------------------------------------------");
+               }
+       
+       suck_init (classpath);
+       native_setclasspath (classpath);
+               
+       unicode_init();
+       heap_init(heapsize, heapstartsize, &dummy);
+       loader_init();
+       compiler_init();
+       ncomp_init();
+
+       native_loadclasses ();
+
+
+   /*********************** JAVA-Klassen laden  ***************************/
+   
+       cp = argv[opt_ind++];
+       for (i=strlen(cp)-1; i>=0; i--) {     /* Punkte im Klassennamen */
+               if (cp[i]=='.') cp[i]='/';        /* auf slashes umbauen */
+               }
+
+       topclass = loader_load ( unicode_new_char (cp) );
+
+       gc_init();
+
+#ifdef USE_THREADS
+       initThreads((u1*)&dummy);                   /* schani */
+#endif
+
+   /************************* Arbeitsroutinen starten ********************/
+
+       if (startit) {
+               methodinfo *mainmethod;
+               java_objectarray *a; 
+
+               mainmethod = class_findmethod (
+                               topclass,
+                               unicode_new_char ("main"), 
+                               unicode_new_char ("([Ljava/lang/String;)V")
+                               );
+               if (!mainmethod) panic ("Can not find method 'void main(String[])'");
+               if ((mainmethod->flags & ACC_STATIC) != ACC_STATIC) panic ("main is not static!");
+                       
+               a = builtin_anewarray (argc - opt_ind, class_java_lang_String);
+               for (i=opt_ind; i<argc; i++) {
+                       a->data[i-opt_ind] = javastring_new (unicode_new_char (argv[i]) );
+                       }
+               exceptionptr = asm_calljavamethod (mainmethod, a, NULL,NULL,NULL );
+       
+               if (exceptionptr) {
+                       printf ("#### Program has thrown: ");
+                       unicode_display (exceptionptr->vftbl->class->name);
+                       printf ("\n");
+                       }
+
+/*             killThread(currentThread); */
+
+               }
+
+       /************* Auf Wunsch alle Methode "ubersetzen ********************/
+
+       if (compileall) {
+               class_compile_methods();
+               }
+
+
+       /******** Auf Wunsch eine spezielle Methode "ubersetzen ***************/
+
+       if (specificmethodname) {
+               methodinfo *m;
+               if (specificsignature)
+                       m = class_findmethod(topclass, 
+                                       unicode_new_char(specificmethodname),
+                                       unicode_new_char(specificsignature));
+               else
+                       m = class_findmethod(topclass, 
+                                       unicode_new_char(specificmethodname), NULL);
+               if (!m) panic ("Specific method not found");
+               if (newcompiler)
+                       (void) new_compile(m);
+               else
+                       (void) compiler_compile(m);
+               }
+
+       /********************* Debug-Tabellen ausgeben ************************/
+                               
+       if (showmethods) class_showmethods (topclass);
+       if (showconstantpool)  class_showconstantpool (topclass);
+       if (showunicode)       unicode_show ();
+
+   
+
+   /************************ Freigeben aller Resourcen *******************/
+
+       compiler_close ();
+       loader_close ();
+       heap_close ();
+       unicode_close ( literalstring_free );
+
+
+   /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+       if (verbose || getcompilingtime || statistics) {
+               log_text ("CACAO terminated");
+               if (statistics)
+                       print_stats ();
+               if (getcompilingtime)
+                       print_times ();
+               mem_usagelog(1);
+               }
+               
+       exit(0);
+       return 1;
+}
+
+
+
+/************************************ SHUTDOWN-Funktion *********************************
+
+       Terminiert das System augenblicklich, ohne den Speicher
+       explizit freizugeben (eigentlich nur f"ur abnorme 
+       Programmterminierung)
+       
+*****************************************************************************************/
+
+void cacao_shutdown(s4 status)
+{
+       if (verbose || getcompilingtime || statistics) {
+               log_text ("CACAO terminated by shutdown");
+               if (statistics)
+                       print_stats ();
+               if (getcompilingtime)
+                       print_times ();
+               mem_usagelog(0);
+               sprintf (logtext, "Exit status: %d\n", (int) status);
+               dolog();
+               }
+               
+       exit(status);
+}
diff --git a/src/cacaoh/headers.c b/src/cacaoh/headers.c
new file mode 100644 (file)
index 0000000..dce631e
--- /dev/null
@@ -0,0 +1,465 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** headers.c **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Dieser Modul ersetzt f"ur den Headerfile-Betrieb den Modul 'main',
+       und 'f"alscht' einige Verweise auf externe Module (damit nicht schon 
+       alle Module des eigentlichen Programmes fertig sein m"ussen, was ja
+       unm"oglich w"are, da die Headerfile-Tabellen ja erst hier und jetzt
+       generiert werden).
+
+       Dieser Modul ist ein ziemlich schneller Hack und dementsprechend
+       schlecht (nicht) kommentiert.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/05/23
+
+*******************************************************************************/
+
+#include "global.h"
+
+#include "tables.h"
+#include "loader.h"
+
+
+/******* verschiedene externe Funktionen "faelschen" (=durch Dummys ersetzen), 
+  damit der Linker zufrieden ist *********/
+functionptr native_findfunction 
+  (unicode *cname, unicode *mname, unicode *desc, bool isstatic)
+{ return NULL; }
+
+java_objectheader *literalstring_new (unicode *text)
+{ return NULL; }
+
+java_objectheader *javastring_new (unicode *text)         /* schani */
+{ return NULL; }
+
+void synchronize_caches() { }
+void asm_call_jit_compiler () { }
+void asm_calljavamethod () { }
+void asm_dumpregistersandcall () { }
+
+s4 new_builtin_idiv (s4 a, s4 b) {return 0;}
+s4 new_builtin_irem (s4 a, s4 b) {return 0;}
+s8 new_builtin_ldiv (s8 a, s8 b) {return 0;}
+s8 new_builtin_lrem (s8 a, s8 b) {return 0;}
+
+
+void new_builtin_monitorenter (java_objectheader *o) {}
+void new_builtin_monitorexit (java_objectheader *o) {}
+
+s4 new_builtin_checkcast(java_objectheader *o, classinfo *c)
+                        {return 0;}
+s4 new_builtin_checkarraycast
+       (java_objectheader *o, constant_arraydescriptor *d)
+       {return 0;}
+
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o) {}
+
+u1 *createcompilerstub (methodinfo *m) {return NULL;}
+u1 *createnativestub (functionptr f, methodinfo *m) {return NULL;}
+u1 *ncreatenativestub (functionptr f, methodinfo *m) {return NULL;}
+
+void removecompilerstub (u1 *stub) {}
+void removenativestub (u1 *stub) {}
+
+void perform_alpha_threadswitch (u1 **from, u1 **to) {}
+u1* initialize_thread_stack (void *func, u1 *stack) { return NULL; }
+u1* used_stack_top (void) { return NULL; }
+
+java_objectheader *native_new_and_init (void *p) { return NULL; }
+
+/************************ globale Variablen **********************/
+
+java_objectheader *exceptionptr;                       /* schani */
+int  newcompiler = true;
+bool verbose =  false;
+
+static chain *nativechain;
+static FILE *file = NULL;
+
+static void printIDpart (int c) 
+{
+               if (     (c>='a' && c<='z')
+                     || (c>='A' && c<='Z')
+                     || (c>='0' && c<='9')
+                     || (c=='_') )          
+                          putc (c,file);
+        else       putc ('_',file);
+
+}
+
+static void printID (unicode *name)
+{
+       int i;
+       for (i=0; i<name->length; i++) {
+               printIDpart (name->text[i]);
+       }
+}
+
+
+u4 outputsize;
+bool dopadding;
+
+static void addoutputsize (int len)
+{
+       u4 newsize,i;
+       if (!dopadding) return;
+
+       newsize = ALIGN (outputsize, len);
+       
+       for (i=outputsize; i<newsize; i++) fprintf (file, "   u1 pad%d\n",(int) i);
+       outputsize = newsize;
+}
+
+
+static u2 *printtype (u2 *desc)
+{
+       u2 c;
+
+       switch (*(desc++)) {
+               case 'V': fprintf (file, "void");
+                         break;
+               case 'I':
+               case 'S':
+               case 'B':
+               case 'C':
+               case 'Z': addoutputsize (4);
+                  fprintf (file, "s4");
+                  break;
+               case 'J': addoutputsize (8);
+                  fprintf (file, "s8");
+                  break;
+               case 'F': addoutputsize (4);
+                  fprintf (file, "float");
+                  break;
+               case 'D': addoutputsize (8);
+                  fprintf (file, "double");
+                  break;
+               case '[':
+                       addoutputsize ( sizeof(java_arrayheader*) ); 
+                       switch (*(desc++)) {
+                               case 'I':  fprintf (file, "java_intarray*"); break;
+                               case 'J':  fprintf (file, "java_longarray*"); break;
+                               case 'Z':  fprintf (file, "java_booleanarray*"); break;
+                               case 'B':  fprintf (file, "java_bytearray*"); break;
+                               case 'S':  fprintf (file, "java_shortarray*"); break;
+                               case 'C':  fprintf (file, "java_chararray*"); break;
+                               case 'F':  fprintf (file, "java_floatarray*"); break;
+                               case 'D':  fprintf (file, "java_doublearray*"); break;
+                               
+                               case '[':  fprintf (file, "java_arrayarray*");
+                                          while ((*desc) == '[') desc++;
+                                          if ((*desc)!='L') desc++;
+                                          else while (*(desc++) != ';');
+                           break;
+                           
+                               case 'L':  fprintf (file, "java_objectarray*");
+                                          while ( *(desc++) != ';');
+                                          break;
+                               default: panic ("invalid type descriptor");
+                               }
+                       break;
+               
+               case 'L': 
+                       addoutputsize ( sizeof(java_objectheader*));
+            fprintf (file, "struct ");
+            while ( (c = *(desc++)) != ';' ) printIDpart (c);           
+            fprintf (file, "*");
+                       break;
+                                       
+               default:  panic ("Unknown type in field descriptor");
+       }
+       
+       return (desc);
+}
+
+
+
+static void printfields (classinfo *c)
+{
+       u4 i;
+       fieldinfo *f;
+       
+       if (!c) {
+               addoutputsize ( sizeof(java_objectheader) );
+               fprintf (file, "   java_objectheader header;\n");
+               return;
+               }
+               
+       printfields (c->super);
+       
+       for (i=0; i<c->fieldscount; i++) {
+               f = &(c->fields[i]);
+               
+               if (! (f->flags & ACC_STATIC) ) {
+                       fprintf (file,"   ");
+                       printtype (f->descriptor->text);
+                       fprintf (file, " ");
+                       unicode_fprint (file, f->name);
+                       fprintf (file, ";\n");
+                       }
+               }
+}
+
+
+
+
+static void remembermethods (classinfo *c)
+{
+       u2 i;
+       methodinfo *m;
+
+       for (i=0; i<c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (m->flags & ACC_NATIVE) {
+                       chain_addlast (nativechain, m);
+                       }
+                                       
+               }
+}
+
+
+
+
+static void printmethod (methodinfo *m)
+{
+       u2 *d;
+       u2 paramnum=1;
+       
+       d = m->descriptor->text;
+       while (*(d++) != ')');
+                               
+       printtype (d);
+       fprintf (file," ");
+       printID (m->class->name);
+       fprintf (file,"_");
+       printID (m->name);
+       fprintf (file," (");
+                                       
+       d = m->descriptor->text+1;
+                       
+       if (! (m->flags & ACC_STATIC) ) {
+               fprintf (file, "struct ");
+               printID (m->class->name);
+               fprintf (file, "* this");
+               if ((*d)!=')') fprintf (file, ", ");
+               }
+                       
+       while ((*d)!=')') {
+               d = printtype (d);
+               fprintf (file, " par%d", paramnum++);
+               if ((*d)!=')') fprintf (file, ", ");
+               }
+                       
+       fprintf (file, ");\n");
+}
+
+
+static void headers_generate (classinfo *c)
+{
+       fprintf (file, "/* Structure information for class: ");
+       unicode_fprint (file, c->name);
+       fprintf (file, " */\n\n");
+
+       fprintf (file, "typedef struct ");
+       printID (c->name);
+       fprintf (file, " {\n");
+       
+       outputsize=0;
+       dopadding=true;
+       printfields (c);
+
+       fprintf (file, "} ");
+       printID (c->name);
+       fprintf (file, ";\n\n");
+
+       remembermethods (c);
+       
+
+       fprintf (file, "\n\n");
+}
+
+
+
+static void printnativetableentry (methodinfo *m)
+{
+       fprintf (file, "   { \"");
+       unicode_fprint (file, m->class->name);
+       fprintf (file, "\",\n     \"");
+       unicode_fprint (file, m->name);
+       fprintf (file, "\",\n     \"");
+       unicode_fprint (file, m->descriptor);
+       fprintf (file, "\",\n     ");
+       if ( (m->flags & ACC_STATIC) !=0)  fprintf (file, "true");
+                                     else fprintf (file, "false");
+       fprintf (file, ",\n     ");
+       fprintf (file, "(functionptr) ");
+       printID (m->class->name);
+       fprintf (file,"_");
+       printID (m->name);
+       fprintf (file,"\n   },\n");
+}
+
+
+
+
+
+static void headers_start ()
+{
+       file = fopen ("nativetypes.hh", "w");
+       if (!file) panic ("Can not open file 'native.h' to store header information");
+       
+       fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
+       fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
+
+       nativechain = chain_new ();
+}
+
+
+static void headers_finish ()
+{
+       methodinfo *m;
+       
+       fprintf (file, "\n/* Prototypes for native methods */\n\n");
+       
+       m = chain_first (nativechain);
+       while (m) {
+               dopadding=false;                
+               printmethod (m);
+               
+               m = chain_next (nativechain);
+               }
+
+
+       file = fopen ("nativetable.hh", "w");
+       if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
+
+       fprintf (file, "/* Table of native methods: nativetables.hh */\n");
+       fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
+
+       while ( (m = chain_first (nativechain)) != NULL) {
+               chain_remove (nativechain);
+               
+               printnativetableentry (m);
+               
+               }
+               
+       chain_free (nativechain);
+       fclose (file);
+}
+
+
+
+
+
+/******************** interne Funktion: print_usage ************************
+
+Gibt die richtige Aufrufsyntax des JAVA-Header-Generators auf stdout aus.
+
+***************************************************************************/
+
+static void print_usage()
+{
+       printf ("USAGE: jch class [class..]\n");
+}   
+
+
+
+
+/************************** Funktion: main *******************************
+
+   Das Hauptprogramm.
+   Wird vom System zu Programstart aufgerufen (eh klar).
+   
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+       s4 i,a;
+       char *cp;
+       classinfo *topclass;
+       void *dummy;
+               
+
+   /********** interne (nur fuer main relevante Optionen) **************/
+   
+       char classpath[500] = "";
+       u4 heapsize = 100000;
+
+   /*********** Optionen, damit wirklich nur headers generiert werden ***/
+   
+   makeinitializations=false;
+   
+
+   /************ Infos aus der Environment lesen ************************/
+
+       cp = getenv ("CLASSPATH");
+       if (cp) {
+               strcpy (classpath + strlen(classpath), ":");
+               strcpy (classpath + strlen(classpath), cp);
+               }
+
+       if (argc < 2) {
+               print_usage ();
+               exit(10);
+               }
+
+
+   /**************************** Programmstart *****************************/
+
+       log_init (NULL);
+       log_text ("Java - header-generator started");
+       
+       
+       suck_init (classpath);
+       
+       unicode_init ();
+       heap_init (heapsize, heapsize, &dummy);
+       loader_init ();
+
+
+   /*********************** JAVA-Klassen laden  ***************************/
+   
+       headers_start ();
+
+       
+       for (a=1; a<argc; a++) {   
+               cp = argv[a];
+               for (i=strlen(cp)-1; i>=0; i--) {     /* Punkte im Klassennamen */
+                       if (cp[i]=='.') cp[i]='/';        /* auf slashes umbauen */
+                       }
+
+               topclass = loader_load ( unicode_new_char (cp) );
+               
+               headers_generate (topclass);
+               }
+       
+
+       headers_finish ();
+
+
+   /************************ Freigeben aller Resourcen *******************/
+
+       loader_close ();
+       heap_close ();
+       unicode_close (NULL);
+       
+
+   /* Endemeldung ausgeben und mit entsprechendem exit-Status terminieren */
+
+       log_text ("Java - header-generator stopped");
+       log_cputime ();
+       mem_usagelog(1);
+       
+       return 0;
+}
+
+
diff --git a/src/mm/memory.c b/src/mm/memory.c
new file mode 100644 (file)
index 0000000..2cc8e94
--- /dev/null
@@ -0,0 +1,458 @@
+/************************* toolbox/memory.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see memory.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "../callargs.h"
+#include "loging.h"
+#include "memory.h"
+
+
+       /********* allgemeine Typen, Variablen und Hilfsfunktionen *********/
+
+#define DUMPBLOCKSIZE  (2<<18)
+#define ALIGNSIZE           8
+
+typedef struct dumplist {
+       struct dumplist *prev;
+       char *dumpmem;
+} dumplist;
+
+
+
+long int memoryusage = 0;
+
+long int dumpsize = 0;
+long int dumpspace = 0;
+dumplist *topdumpblock = NULL;
+
+long int maxmemusage = 0;
+long int maxdumpsize = 0;
+
+/* #define TRACECALLARGS */
+
+#ifdef TRACECALLARGS
+static char  nomallocmem[16777216];
+static char *nomalloctop = nomallocmem + 16777216;
+static char *nomallocptr = nomallocmem;
+
+static void *lit_checked_alloc (int length)
+{
+       void *m;
+
+       nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
+       
+       m = nomallocptr;
+       nomallocptr += length;
+       if (nomallocptr > nomalloctop) panic ("Out of memory");
+       return m;
+}
+
+#else
+
+static void *lit_checked_alloc (int length)
+{
+       void *m = malloc(length);
+       if (!m) panic ("Out of memory");
+       return m;
+}
+
+#endif
+
+
+static void *checked_alloc (int length)
+{
+       void *m = malloc(length);
+       if (!m) panic ("Out of memory");
+       return m;
+}
+
+static int mmapcodesize = 0;
+static void *mmapcodeptr = NULL;
+
+void *mem_mmap(int length)
+{
+       void *retptr;
+
+       length = (ALIGN(length,ALIGNSIZE));
+       if (length > mmapcodesize) {
+               mmapcodesize = 0x10000;
+               if (length > mmapcodesize)
+                       mmapcodesize = length;
+               mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
+               mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
+                             PROT_READ | PROT_WRITE | PROT_EXEC,
+                             MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
+               if (mmapcodeptr == (void*) -1)
+                       panic ("Out of memory");
+               }
+       retptr = mmapcodeptr;
+       mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
+       mmapcodesize -= length;
+       return retptr;
+}
+
+
+#ifdef DEBUG
+
+       /************ Sichere Version des Speichermanages **************/
+
+
+typedef struct memblock {
+       struct memblock *prev,*next;
+       int length;
+} memblock;
+
+#define BLOCKOFFSET    (ALIGN(sizeof(memblock),ALIGNSIZE))
+
+struct memblock *firstmemblock;
+
+
+
+void *mem_alloc(int length)
+{
+       memblock *mb;
+
+       if (length==0) return NULL;
+       mb = checked_alloc (length + BLOCKOFFSET);
+
+       mb -> prev = NULL;
+       mb -> next = firstmemblock;     
+       mb -> length = length;
+
+       if (firstmemblock) firstmemblock -> prev = mb;
+       firstmemblock = mb;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+       return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void *lit_mem_alloc(int length)
+{
+       memblock *mb;
+
+       if (length==0) return NULL;
+       mb = lit_checked_alloc (length + BLOCKOFFSET);
+
+       mb -> prev = NULL;
+       mb -> next = firstmemblock;     
+       mb -> length = length;
+
+       if (firstmemblock) firstmemblock -> prev = mb;
+       firstmemblock = mb;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+       return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void mem_free(void *m, int length)
+{
+       memblock *mb;
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+       
+       if (mb->length != length) {
+               sprintf (logtext, 
+                        "Memory block of size %d has been return as size %d",
+                        mb->length, length);
+               error();
+               }
+               
+       if (mb->prev) mb->prev->next = mb->next;
+                else firstmemblock = mb->next;
+       if (mb->next) mb->next->prev = mb->prev;
+
+       free (mb);
+
+       memoryusage -= length;
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+       memblock *mb;
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+       
+       if (mb->length != length) {
+               sprintf (logtext, 
+                        "Memory block of size %d has been return as size %d",
+                        mb->length, length);
+               error();
+               }
+               
+       if (mb->prev) mb->prev->next = mb->next;
+                else firstmemblock = mb->next;
+       if (mb->next) mb->next->prev = mb->prev;
+
+#ifdef TRACECALLARGS
+#else
+       free (mb);
+#endif
+
+       memoryusage -= length;
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+       void *m2;
+       
+       m2 = mem_alloc (len2);
+       memcpy (m2, m1, len1);
+       mem_free (m1, len1);
+
+       return m2;
+}
+
+
+
+
+static void mem_characterlog (unsigned char *m, int len)
+{
+#      define LINESIZE 16
+       int z,i;
+       
+       for (z=0; z<len; z+=LINESIZE) {
+               sprintf (logtext, "   ");
+                       
+               for (i=z; i<(z+LINESIZE) && i<len; i++) {
+                       sprintf (logtext+strlen(logtext), "%2x ", m[i]);
+                       }
+               for (; i<(z+LINESIZE); i++) {
+                       sprintf (logtext+strlen(logtext), "   ");
+                       }
+                                       
+               sprintf (logtext+strlen(logtext),"   ");
+               for (i=z; i<(z+LINESIZE) && i<len; i++) {
+                       sprintf (logtext+strlen(logtext),
+                            "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
+                       }
+                       
+               dolog();
+               }
+}
+
+#else
+               /******* Schnelle Version des Speichermanagers ******/
+
+
+void *mem_alloc(int length)
+{
+       if (length==0) return NULL;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+       
+       return checked_alloc (length);
+}
+
+
+void *lit_mem_alloc(int length)
+{
+       if (length==0) return NULL;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+       
+       return lit_checked_alloc (length);
+}
+
+
+void mem_free(void *m, int length)
+{
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       memoryusage -= length;
+
+       free (m);
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       memoryusage -= length;
+
+#ifdef TRACECALLARGS
+#else
+       free (m);
+#endif
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+       void *m2;
+
+       if (!m1) {
+               if (len1!=0) 
+                 panic ("reallocating memoryblock with address NULL, length != 0");
+               }
+               
+       memoryusage = (memoryusage - len1) + len2;
+
+       m2 = realloc (m1, len2);
+       if (!m2) panic ("Out of memory");
+       return m2;
+}
+
+
+#endif
+
+               /******* allgemeine Teile des Speichermanagers ******/
+
+
+
+long int mem_usage()
+{
+       return memoryusage;
+}
+
+
+
+
+
+void *dump_alloc(int length)
+{
+       void *m;
+
+        if (length==0) return NULL;
+       
+       length = ALIGN (length, ALIGNSIZE);
+
+       assert (length <= DUMPBLOCKSIZE);
+       assert (length > 0);
+
+       if (dumpsize + length > dumpspace) {
+               dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
+
+               newdumpblock -> prev = topdumpblock;
+               topdumpblock = newdumpblock;
+
+               newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
+
+               dumpsize = dumpspace;
+               dumpspace += DUMPBLOCKSIZE;             
+               }
+       
+       m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
+       dumpsize += length;
+       
+       if (dumpsize > maxdumpsize) {
+               maxdumpsize = dumpsize;
+               }
+               
+       return m;
+}   
+
+
+void *dump_realloc(void *ptr, int len1, int len2)
+{
+       void *p2 = dump_alloc (len2);
+       memcpy (p2, ptr, len1); 
+       return p2;
+}
+
+
+long int dump_size()
+{
+       return dumpsize;
+}
+
+
+void dump_release(long int size)
+{
+       assert (size >= 0 && size <= dumpsize);
+
+       dumpsize = size;
+       
+       while (dumpspace  >  dumpsize + DUMPBLOCKSIZE) {
+               dumplist *oldtop = topdumpblock;
+               
+               topdumpblock = oldtop -> prev;
+               dumpspace -= DUMPBLOCKSIZE;
+               
+#ifdef TRACECALLARGS
+#else
+               free (oldtop -> dumpmem);
+               free (oldtop);
+#endif
+               }               
+}
+
+
+
+
+void mem_usagelog (int givewarnings)
+{
+       if ((memoryusage!=0) && givewarnings) {
+               sprintf (logtext, "Allocated memory not returned: %d",
+                     (int)memoryusage);
+               dolog();
+
+#ifdef DEBUG
+               { 
+               memblock *mb = firstmemblock;
+               while (mb) {
+                       sprintf (logtext, "   Memory block size: %d", 
+                         (int)(mb->length) );
+                       dolog();
+                       mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
+                       mb = mb->next;
+                       }
+               }
+#endif
+                       
+               }
+
+       if ((dumpsize!=0) && givewarnings) {
+               sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
+               dolog();
+               }
+
+
+       sprintf (logtext, "Random/Dump - memory usage: %dK/%dK", 
+             (int)((maxmemusage+1023)/1024), 
+             (int)((maxdumpsize+1023)/1024) );
+       dolog();
+       
+}
+
diff --git a/src/mm/memory.h b/src/mm/memory.h
new file mode 100644 (file)
index 0000000..c4122f9
--- /dev/null
@@ -0,0 +1,121 @@
+/************************* toolbox/memory.h ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Headerfiles und Makros f"ur die Speicherverwaltung.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define CODEMMAP
+
+#define ALIGN(pos,size)       ( ( ((pos)+(size)-1) / (size))*(size) )
+#define PADDING(pos,size)     ( ALIGN((pos),(size)) - (pos) )
+#define OFFSET(s,el)          ( (int) &( ((s*)0) -> el ) )
+
+
+#define NEW(type)             ((type*) mem_alloc ( sizeof(type) ))
+#define FREE(ptr,type)        mem_free (ptr, sizeof(type) )
+
+#define LNEW(type)             ((type*) lit_mem_alloc ( sizeof(type) ))
+#define LFREE(ptr,type)        lit_mem_free (ptr, sizeof(type) )
+
+#define MNEW(type,num)        ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define MFREE(ptr,type,num)   mem_free (ptr, sizeof(type) * (num) )
+#define MREALLOC(ptr,type,num1,num2) mem_realloc (ptr, sizeof(type) * (num1), \
+                                                       sizeof(type) * (num2) )
+
+#define DNEW(type)            ((type*) dump_alloc ( sizeof(type) ))
+#define DMNEW(type,num)       ((type*) dump_alloc ( sizeof(type) * (num) ))
+#define DMREALLOC(ptr,type,num1,num2)  dump_realloc (ptr, sizeof(type)*(num1),\
+                                                       sizeof(type) * (num2) )
+
+#define MCOPY(dest,src,type,num)  memcpy (dest,src, sizeof(type)* (num) )
+
+#ifdef CODEMMAP
+#define CNEW(type,num)        ((type*) mem_mmap ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)
+#else
+#define CNEW(type,num)        ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)        mem_free (ptr, num)
+#endif
+
+void *mem_alloc(int length);
+void *mem_mmap(int length);
+void *lit_mem_alloc(int length);
+void mem_free(void *m, int length);
+void lit_mem_free(void *m, int length);
+void *mem_realloc(void *m, int len1, int len2);
+long int mem_usage();
+
+void *dump_alloc(int length);
+void *dump_realloc(void *m, int len1, int len2);
+long int dump_size();
+void dump_release(long int size);
+
+void mem_usagelog(int givewarnings);
+/* 
+---------------------------- Schnittstellenbeschreibung -----------------------
+
+Der Speicherverwalter hat zwei m"ogliche Arten Speicher zu reservieren
+und freizugeben:
+
+       1.   explizites Anfordern / Freigeben
+
+                       mem_alloc ..... Anfordern eines Speicherblocks 
+                       mem_free ...... Freigeben eines Speicherblocks
+                       mem_realloc ... Vergr"o"sern eines Speicherblocks (wobei 
+                                       der Inhalt eventuell an eine neue Position kommt)
+                       mem_usage ..... Menge des bereits belegten Speichers
+
+
+       2.   explizites Anfordern und automatisches Freigeben
+       
+                       dump_alloc .... Anfordern eines Speicherblocks vom
+                                       (wie ich es nenne) DUMP-Speicher
+                       dump_realloc .. Vergr"o"sern eines Speicherblocks
+                       dump_size ..... Merkt sich eine Freigabemarke am Dump
+                       dump_release .. Gibt allen Speicher, der nach der Marke angelegt 
+                                       worden ist, wieder frei.
+                                       
+       
+Es gibt f"ur diese Funktionen ein paar praktische Makros:
+
+       NEW (type) ....... legt Speicher f"ur ein Element des Typs `type` an.
+       FREE (ptr,type) .. gibt Speicher zur"uck
+       
+       MNEW (type,num) .. legt Speicher f"ur ein ganzes Array an
+       MFREE (ptr,type,num) .. gibt den Speicher wieder her
+       
+       MREALLOC (ptr,type,num1,num2) .. vergr"o"sert den Speicher f"ur das Array
+                                        auf die Gr"o"se num2
+                                        
+Die meisten der Makros gibt es auch f"ur den DUMP-Speicher, na"mlich mit
+gleichem Namen, nur mit vorangestelltem 'D', also:     
+       
+       DNEW,  DMNEW, DMREALLOC   (DFREE gibt es nat"urlich keines)
+
+
+-------------------------------------------------------------------------------
+
+Die restlichen Makros:
+
+       ALIGN (pos, size) ... Rundet den Wert von 'pos' auf die n"achste durch
+                             'size' teilbare Zahl auf.
+                             
+       
+       OFFSET (s,el) ....... Berechnet den Offset (in Bytes) des Elementes 'el'   
+                             in der Struktur 's'.
+                             
+       MCOPY (dest,src,type,num) ... Kopiert 'num' Elemente vom Typ 'type'.
+       
+
+*/
diff --git a/src/native/native.c b/src/native/native.c
new file mode 100644 (file)
index 0000000..771ec54
--- /dev/null
@@ -0,0 +1,340 @@
+/****************************** native.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt die Tabellen f"ur die native-methods.
+       Die vom Headerfile-Generator erzeugten -.hh - Dateien werden hier
+       eingebunden, und ebenso alle C-Funktionen, mit denen diese
+       Methoden implementiert werden.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+
+#include "global.h"
+#include "native.h"
+
+#include "builtin.h"
+#include "nativetypes.hh"
+#include "asmpart.h"
+#include "tables.h"
+#include "loader.h"
+
+
+java_objectheader* exceptionptr = NULL;
+
+
+
+static char *classpath;
+
+
+/******************** die f"r die native-Methoden n"otigen Systemklassen *****/
+
+static classinfo *class_java_lang_Class;
+static classinfo *class_java_lang_Cloneable;
+static classinfo *class_java_lang_CloneNotSupportedException;
+static classinfo *class_java_lang_Double;
+static classinfo *class_java_lang_Float;
+static classinfo *class_java_io_IOException;
+static classinfo *class_java_lang_ClassNotFoundException;
+static classinfo *class_java_lang_InstantiationException;
+
+
+
+/************************** alle Funktionen einbinden ************************/ 
+
+#include "nat/lang.c"
+#include "nat/io.c"
+#include "nat/util.c"
+
+
+/********************** Tabellen f"ur die Methoden ***************************/
+
+static struct nativeref {
+       char *classname;
+       char *methodname;
+       char *descriptor;
+       bool isstatic;
+       functionptr func;
+} nativetable [] = {
+
+#include "nativetable.hh"
+
+};
+
+
+#define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
+
+static struct nativecompref {
+       unicode *classname;
+       unicode *methodname;
+       unicode *descriptor;
+       bool isstatic;
+       functionptr func;
+       } nativecomptable [NATIVETABLESIZE];
+
+static bool nativecompdone = false;
+
+
+/*********************** Funktion: native_loadclasses **************************
+
+       L"adt alle Klassen, die die native Methoden zus"atzlich ben"otigen 
+
+*******************************************************************************/
+
+void native_loadclasses()
+{
+       class_java_lang_Cloneable = 
+               loader_load ( unicode_new_char ("java/lang/Cloneable") );
+       class_java_lang_CloneNotSupportedException = 
+               loader_load ( unicode_new_char ("java/lang/CloneNotSupportedException") );
+       class_java_lang_Class =
+               loader_load ( unicode_new_char ("java/lang/Class") );
+       class_java_lang_Double =
+               loader_load ( unicode_new_char ("java/lang/Double") );
+       class_java_lang_Float =
+               loader_load ( unicode_new_char ("java/lang/Float") );
+       class_java_io_IOException = 
+               loader_load ( unicode_new_char ("java/io/IOException") );
+       class_java_lang_ClassNotFoundException =
+               loader_load ( unicode_new_char ("java/lang/ClassNotFoundException") );
+       class_java_lang_InstantiationException=
+               loader_load ( unicode_new_char ("java/lang/InstantiationException") );
+       
+}
+
+/********************* Funktion: native_setclasspath ***************************/
+void native_setclasspath (char *path)
+{
+       classpath = path;
+}
+
+
+/*********************** Funktion: native_findfunction ************************
+
+       Sucht in der Tabelle die passende Methode (muss mit Klassennamen,
+       Methodennamen, Descriptor und 'static'-Status "ubereinstimmen),
+       und gibt den Funktionszeiger darauf zur"uck.
+       Return: Funktionszeiger oder NULL  (wenn es keine solche Methode gibt)
+
+       Anmerkung: Zu Beschleunigung des Suchens werden die als C-Strings
+          vorliegenden Namen/Descriptors in entsprechende unicode-Symbole
+          umgewandelt (beim ersten Aufruf dieser Funktion).
+
+*******************************************************************************/
+
+functionptr native_findfunction (unicode *cname, unicode *mname, 
+                                 unicode *desc, bool isstatic)
+{
+       u4 i;
+       struct nativecompref *n;
+
+       isstatic = isstatic ? true : false;
+
+       if (!nativecompdone) {
+               for (i=0; i<NATIVETABLESIZE; i++) {
+                       nativecomptable[i].classname   = 
+                                       unicode_new_char(nativetable[i].classname);
+                       nativecomptable[i].methodname  = 
+                                       unicode_new_char(nativetable[i].methodname);
+                       nativecomptable[i].descriptor  = 
+                                       unicode_new_char(nativetable[i].descriptor);
+                       nativecomptable[i].isstatic    = 
+                                       nativetable[i].isstatic;
+                       nativecomptable[i].func        = 
+                                       nativetable[i].func;
+                       }
+               nativecompdone = true;
+               }
+
+       for (i=0; i<NATIVETABLESIZE; i++) {
+               n = &(nativecomptable[i]);
+
+               if (cname==n->classname && mname==n->methodname &&
+                   desc==n->descriptor && isstatic==n->isstatic)  return n->func;
+               }
+
+       return NULL;
+}
+
+
+/********************** Funktion: javastring_new *****************************
+
+       Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+       das "ubergebene unicode-Symbol ein. 
+       Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new (unicode *text)
+{
+       u4 i;
+       java_lang_String *s;
+       java_chararray *a;
+       
+       s = (java_lang_String*) builtin_new (class_java_lang_String);
+       a = builtin_newarray_char (text->length);
+
+       if ( (!a) || (!s) ) return NULL;
+
+       for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = text->length;
+
+       return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: javastring_new_char ************************
+
+       Legt ein neues Objekt vom Typ java/lang/String an, und tr"agt als Text
+       den "ubergebenen C-String ein. 
+       Return: Zeiger auf den String, oder NULL (wenn Speicher aus)
+
+*****************************************************************************/
+
+java_objectheader *javastring_new_char (char *text)
+{
+       u4 i;
+       u4 len = strlen(text);
+       java_lang_String *s;
+       java_chararray *a;
+       
+       s = (java_lang_String*) builtin_new (class_java_lang_String);
+       a = builtin_newarray_char (len);
+
+       if ( (!a) || (!s) ) return NULL;
+
+       for (i=0; i<len; i++) a->data[i] = text[i];
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = len;
+
+       return (java_objectheader*) s;
+}
+
+
+/************************* Funktion: javastring_tochar *****************************
+
+       Macht aus einem java-string einen C-String, und liefert den Zeiger
+       darauf zur"uck. 
+       Achtung: Beim n"achsten Aufruf der Funktion wird der vorige String 
+       "uberschrieben
+       
+***********************************************************************************/
+
+#define MAXSTRINGSIZE 1000
+char stringbuffer[MAXSTRINGSIZE];
+
+char *javastring_tochar (java_objectheader *so) 
+{
+       java_lang_String *s = (java_lang_String*) so;
+       java_chararray *a;
+       u4 i;
+       
+       if (!s) return "";
+       a = s->value;
+       if (!a) return "";
+       if (s->count > MAXSTRINGSIZE) return "";
+       for (i=0; i<s->count; i++) stringbuffer[i] = a->data[s->offset+i];
+       stringbuffer[i] = '\0';
+       return stringbuffer;
+}
+
+
+/******************** Funktion: native_new_and_init *************************
+
+       Legt ein neues Objekt einer Klasse am Heap an, und ruft automatisch
+       die Initialisierungsmethode auf.
+       Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+                       mehr frei ist.
+                       
+*****************************************************************************/
+
+java_objectheader *native_new_and_init (classinfo *c)
+{
+       methodinfo *m;
+       java_objectheader *o = builtin_new (c);
+
+       if (!o) return NULL;
+       
+       m = class_findmethod (c, 
+                             unicode_new_char ("<init>"), 
+                             unicode_new_char ("()V"));
+       if (!m) {
+               log_text ("warning: class has no instance-initializer:");
+               unicode_sprint (logtext, c->name);
+               dolog();
+               return o;
+               }
+
+       asm_calljavamethod (m, o,NULL,NULL,NULL);
+       return o;
+}
+
+
+/********************* Funktion: literalstring_new ****************************
+
+       erzeugt einen Java-String mit dem angegebenen Text, allerdings nicht
+       auf dem HEAP, sondern in einem anderen Speicherbereich (der String
+       muss dann sp"ater explizit wieder freigegeben werden).
+       Alle Strings, die auf diese Art erzeugt werden, werden in einer
+       gemeinsamen Struktur gespeichert (n"amlich auch "uber die
+       Unicode-Hashtabelle), sodass identische Strings auch wirklich den
+       gleichen Zeiger liefern.
+       
+******************************************************************************/
+
+java_objectheader *literalstring_new (unicode *text)
+{
+       u4 i;
+       java_lang_String *s;
+       java_chararray *a;
+
+       if (text->string) return text->string;
+       
+       a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(text->length-1) );
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = text->length;
+       a -> header.arraytype = ARRAYTYPE_CHAR;
+       for (i=0; i<text->length; i++) a->data[i] = text->text[i];
+
+       s = LNEW (java_lang_String);
+       s -> header.vftbl = class_java_lang_String -> vftbl;
+       s -> value = a;
+       s -> offset = 0;
+       s -> count = text->length;
+
+       unicode_setstringlink (text, (java_objectheader*) s);
+       return (java_objectheader*) s;
+}
+
+
+/********************** Funktion: literalstring_free **************************
+
+       L"oscht einen Java-String wieder aus dem Speicher (wird zu Systemende
+       vom Hashtabellen-Verwalter aufgerufen)
+
+******************************************************************************/
+
+void literalstring_free (java_objectheader* sobj)
+{
+       java_lang_String *s = (java_lang_String*) sobj;
+       java_chararray *a = s->value;
+       
+       LFREE (s, java_lang_String);
+       LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1));
+}
+
+
+
diff --git a/src/native/native.h b/src/native/native.h
new file mode 100644 (file)
index 0000000..c484642
--- /dev/null
@@ -0,0 +1,35 @@
+/****************************** native.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (PCMDs).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/03/12
+
+*******************************************************************************/
+
+
+extern java_objectheader* exceptionptr;
+
+void native_loadclasses ();
+void native_setclasspath (char *path);
+
+functionptr native_findfunction (unicode *cname, unicode *mname, 
+                                 unicode *desc, bool isstatic);
+
+java_objectheader *javastring_new (unicode *text);
+java_objectheader *javastring_new_char (char *text);
+char *javastring_tochar (java_objectheader *s);
+
+java_objectheader *native_new_and_init (classinfo *c);
+
+java_objectheader *literalstring_new (unicode *text);
+void literalstring_free (java_objectheader*);
+
+void attach_property(char *name, char *value);
diff --git a/src/threads/green/locks.c b/src/threads/green/locks.c
new file mode 100644 (file)
index 0000000..f921f47
--- /dev/null
@@ -0,0 +1,576 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * locks.c
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "thread.h"
+#include "locks.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+
+static classinfo *class_java_lang_IllegalMonitorStateException;
+
+#if 1
+#define DBG(s)
+#else
+#define DBG(s)   s
+#endif
+
+extern thread* currentThread;
+
+#if defined(USE_INTERNAL_THREADS)
+
+mutexHashEntry *mutexHashTable;
+int mutexHashTableSize;
+long mutexHashMask;
+
+mutexHashEntry *mutexOverflowTable;
+int mutexOverflowTableSize;
+mutexHashEntry *firstFreeOverflowEntry = 0;
+
+conditionHashEntry *conditionHashTable;
+int conditionHashTableSize;
+long conditionHashMask;
+
+/*
+ * Init the tables.
+ */
+void
+initLocks (void)
+{
+    int i;
+
+    mutexHashTableSize = MUTEX_HASH_TABLE_SIZE;
+    mutexHashTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry) * mutexHashTableSize);
+    mutexHashMask = (mutexHashTableSize - 1) << 3;
+
+    for (i = 0; i < mutexHashTableSize; ++i)
+    {
+               mutexHashTable[i].object = 0;
+               mutexHashTable[i].mutex.holder = 0;
+               mutexHashTable[i].mutex.count = 0;
+               mutexHashTable[i].mutex.muxWaiters = 0;
+               mutexHashTable[i].conditionCount = 0;
+               mutexHashTable[i].next = 0;
+    }
+
+    mutexOverflowTableSize = MUTEX_OVERFLOW_TABLE_SIZE;
+    mutexOverflowTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry)
+                                                                                                * mutexOverflowTableSize);
+
+    firstFreeOverflowEntry = &mutexOverflowTable[0];
+
+    for (i = 0; i < mutexOverflowTableSize; ++i)
+    {
+               mutexOverflowTable[i].object = 0;
+               mutexOverflowTable[i].mutex.holder = 0;
+               mutexOverflowTable[i].mutex.count = 0;
+               mutexOverflowTable[i].mutex.muxWaiters = 0;
+               mutexOverflowTable[i].conditionCount = 0;
+               mutexOverflowTable[i].next = &mutexOverflowTable[i + 1];
+    }
+    mutexOverflowTable[i - 1].next = 0;
+
+    conditionHashTableSize = CONDITION_HASH_TABLE_SIZE;
+    conditionHashTable = (conditionHashEntry*)malloc(sizeof(conditionHashEntry)
+                                                                                                        * conditionHashTableSize);
+    conditionHashMask = (conditionHashTableSize - 1) << 3;
+
+    for (i = 0; i < conditionHashTableSize; ++i)
+    {
+               conditionHashTable[i].object = 0;
+               conditionHashTable[i].condition.cvWaiters = 0;
+               conditionHashTable[i].condition.mux = 0;
+    }
+
+       /* Load exception classes */
+       class_java_lang_IllegalMonitorStateException =
+               loader_load(unicode_new_char("java/lang/IllegalMonitorStateException"));
+}
+
+/*
+ * Reorders part of the condition hash table. Must be called after an entry has been deleted.
+ */
+void
+reorderConditionHashTable (int begin)
+{
+    while (conditionHashTable[begin].object != 0)
+    {
+       int hashValue = CONDITION_HASH_VALUE(conditionHashTable[begin].object);
+
+       if (hashValue != begin)
+       {
+           while (conditionHashTable[hashValue].object != 0)
+           {
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+               if (hashValue == begin)
+                   break;
+           }
+           if (hashValue != begin)
+           {
+               conditionHashTable[hashValue] = conditionHashTable[begin];
+               conditionHashTable[begin].object = 0;
+               conditionHashTable[begin].condition.cvWaiters = 0;
+               conditionHashTable[begin].condition.mux = 0;
+           }
+       }
+
+       begin = CONDITION_HASH_SUCCESSOR(begin);
+    }
+}
+
+/*
+ * Looks up an entry in the condition hash table.
+ */
+iCv*
+conditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != object
+                  && conditionHashTable[hashValue].object != 0)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    if (conditionHashTable[hashValue].object == 0)
+    {
+               intsRestore();
+               return 0;
+    }
+    
+    intsRestore();
+    return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Adds a new entry in the condition hash table and returns a pointer to the condition
+ */
+iCv*
+addConditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != 0)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    conditionHashTable[hashValue].object = object;
+
+    intsRestore();
+
+    return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Removes an entry from the condition hash table.
+ */
+void
+removeConditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != object)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    conditionHashTable[hashValue].object = 0;
+    conditionHashTable[hashValue].condition.cvWaiters = 0;
+    conditionHashTable[hashValue].condition.mux = 0;
+
+    reorderConditionHashTable(CONDITION_HASH_SUCCESSOR(hashValue));
+
+    intsRestore();
+}
+
+/*
+ * Returns the mutex entry for the specified object and increments its conditionCount.
+ */
+mutexHashEntry*
+conditionLockedMutexForObject (java_objectheader *object)
+{
+    int hashValue;
+    mutexHashEntry *entry;
+
+    assert(object != 0);
+
+    intsDisable();
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object != 0)
+    {
+               if (entry->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       entry->object = 0;
+                       entry->mutex.holder = 0;
+                       entry->mutex.count = 0;
+                       entry->mutex.muxWaiters = 0;
+               }
+               else
+               {
+                       while (entry->next != 0 && entry->object != object)
+                               entry = entry->next;
+
+                       if (entry->object != object)
+                       {
+                               entry->next = firstFreeOverflowEntry;
+                               firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+                               
+                               entry = entry->next;
+                               entry->object = 0;
+                               entry->next = 0;
+                               assert(entry->conditionCount == 0);
+                       }
+               }
+    }
+
+    if (entry->object == 0)
+        entry->object = object;
+
+    ++entry->conditionCount;
+
+    intsRestore();
+
+    return entry;
+}
+
+/*
+ * Wait for the condition of an object to be signalled
+ */
+void
+wait_cond_for_object (java_objectheader *obj, s8 time)
+{
+    iCv *condition;
+    mutexHashEntry *mutexEntry;
+
+    intsDisable();
+
+    mutexEntry = conditionLockedMutexForObject(obj);
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+    internal_wait_cond(&mutexEntry->mutex, condition, time);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+    --mutexEntry->conditionCount;
+
+    intsRestore();
+}
+
+/*
+ * Signal the condition of an object
+ */
+void
+signal_cond_for_object (java_objectheader *obj)
+{
+    iCv *condition;
+
+    intsDisable();
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+    
+    internal_signal_cond(condition);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+
+    intsRestore();
+}
+
+/*
+ * Broadcast the condition of an object.
+ */
+void
+broadcast_cond_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_broadcast_cond_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Internal: Broadcast the condition of an object.
+ */
+void
+internal_broadcast_cond_for_object (java_objectheader *obj)
+{
+    iCv *condition;
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    internal_broadcast_cond(condition);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+}
+
+/*
+ * Lock a mutex.
+ */
+void
+lock_mutex (iMux *mux)
+{
+       intsDisable();
+       internal_lock_mutex(mux);
+       intsRestore();
+}
+
+/*
+ * Lock the mutex for an object.
+ */
+void
+lock_mutex_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_lock_mutex_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Unlock a mutex.
+ */
+void
+unlock_mutex (iMux *mux)
+{
+       intsDisable();
+       internal_unlock_mutex(mux);
+       intsRestore();
+}
+
+/*
+ * Unlock the mutex for an object.
+ */
+void
+unlock_mutex_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_unlock_mutex_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Wait on a condition variable.
+ */
+void
+wait_cond (iMux *mux, iCv *cond, s8 timeout)
+{
+       intsDisable();
+       internal_wait_cond(mux, cond, timeout);
+       intsRestore();
+}
+
+/*
+ * Signal a condition variable.
+ */
+void
+signal_cond (iCv *cond)
+{
+       intsDisable();
+       internal_signal_cond(cond);
+       intsRestore();
+}
+
+/*
+ * Broadcast a condition variable.
+ */
+void
+broadcast_cond (iCv *cond)
+{
+       intsDisable();
+       internal_broadcast_cond(cond);
+       intsRestore();
+}
+
+/*
+ * Internal: Lock a mutex.
+ */
+void
+internal_lock_mutex(iMux* mux)
+{
+       assert(blockInts == 1);
+
+    if (mux->holder == 0)
+    {
+               mux->holder = currentThread;
+               mux->count = 1;
+               DBG( fprintf(stderr, "set holder of %p to %p\n", mux, mux->holder); )
+    }
+    else if (mux->holder == currentThread)
+    {
+               mux->count++;
+    }
+    else
+    {
+               while (mux->holder != 0)
+               {
+                       suspendOnQThread(currentThread, &mux->muxWaiters);
+               }
+               mux->holder = currentThread;
+               mux->count = 1;
+    }
+}
+
+/*
+ * Internal: Release a mutex.
+ */
+void
+internal_unlock_mutex(iMux* mux)
+{
+    thread* tid;
+
+       assert(blockInts == 1);
+
+    assert(mux->holder == currentThread);
+    
+    mux->count--;
+    if (mux->count == 0)
+    {
+               mux->holder = 0;
+               if (mux->muxWaiters != 0)
+               {
+                       tid = mux->muxWaiters;
+                       mux->muxWaiters = tid->next;
+                       iresumeThread(tid);
+               }
+    }
+}
+
+/*
+ * Internal: Wait on a conditional variable.
+ *  (timeout currently ignored)
+ */
+void
+internal_wait_cond(iMux* mux, iCv* cv, s8 timeout)
+{
+    int count;
+    thread* tid;
+
+    DBG( fprintf(stderr, "waiting on %p\n", cv); );
+
+    if (mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    count = mux->count;
+    mux->holder = 0;
+    mux->count = 0;
+    cv->mux = mux;
+
+    /* If there's anyone waiting here, wake them up */
+    if (mux->muxWaiters != 0) {
+               tid = mux->muxWaiters;
+               mux->muxWaiters = tid->next;
+               iresumeThread(tid);
+    }
+
+    /* Suspend, and keep suspended until I re-get the lock */
+    suspendOnQThread(currentThread, &cv->cvWaiters);
+    while (mux->holder != 0) {
+               DBG( fprintf(stderr, "woke up\n"); );
+               suspendOnQThread(currentThread, &mux->muxWaiters);
+    }
+
+    mux->holder = currentThread;
+    mux->count = count;
+}
+
+/*
+ * Internal: Wake one thread on a conditional variable.
+ */
+void
+internal_signal_cond (iCv* cv)
+{
+    thread* tid;
+
+    DBG( fprintf(stderr, "signalling on %p\n", cv); );
+
+    /* If 'mux' isn't set then we've never waited on this object. */
+    if (cv->mux == 0) {
+               return;
+    }
+
+    if (cv->mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    /* Remove one thread from cv list */
+    if (cv->cvWaiters != 0) {
+               DBG( fprintf(stderr, "releasing a waiter\n"); );
+
+               tid = cv->cvWaiters;
+               cv->cvWaiters = tid->next;
+
+               /* Place it on mux list */
+               tid->next = cv->mux->muxWaiters;
+               cv->mux->muxWaiters = tid;
+    }
+}
+
+/*
+ * Internal: Wake all threads on a conditional variable.
+ */
+void
+internal_broadcast_cond (iCv* cv)
+{
+    thread** tidp;
+
+    /* If 'mux' isn't set then we've never waited on this object. */
+    if (cv->mux == 0) {
+               return;
+    }
+
+    if (cv->mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    /* Find the end of the cv list */
+    if (cv->cvWaiters) {
+               for (tidp = &cv->cvWaiters; *tidp != 0; tidp = &(*tidp)->next)
+                       ;
+
+               /* Place entire cv list on mux list */
+               (*tidp) = cv->mux->muxWaiters;
+               cv->mux->muxWaiters = cv->cvWaiters;
+               cv->cvWaiters = 0;
+    }
+}
+
+#endif
diff --git a/src/threads/green/locks.h b/src/threads/green/locks.h
new file mode 100644 (file)
index 0000000..e522467
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * locks.h
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __locks_h
+#define __locks_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+#include "sysdep/defines.h"
+
+#define        WAITFOREVER     -1
+
+#if defined(USE_INTERNAL_THREADS)
+
+struct _thread;
+
+typedef struct _iMux {
+    struct _thread *holder;
+    int        count;
+    struct _thread *muxWaiters;
+} iMux;
+
+typedef struct _iCv {
+       struct _thread*         cvWaiters;
+       struct _iMux*           mux;
+} iCv;
+
+#define MAX_MUTEXES             256
+
+typedef struct _mutexHashEntry
+{
+    java_objectheader *object;
+    iMux mutex;
+    struct _mutexHashEntry *next;
+    int conditionCount;
+} mutexHashEntry;
+
+#define MUTEX_HASH_TRASH_BITS                3
+#define MUTEX_HASH_SIGN_BITS                10
+
+#define MUTEX_HASH_TABLE_SIZE             1024
+#define MUTEX_OVERFLOW_TABLE_SIZE         1024
+/*
+#define MAX_MUTEX_HASH_TABLE_SIZE        65536
+*/
+
+/*
+#define MUTEX_USE_THRESHOLD               1024
+*/
+
+extern long mutexHashMask;
+extern int mutexHashTableSize;
+extern mutexHashEntry *mutexHashTable;
+
+extern mutexHashEntry *mutexOverflowTable;
+extern int mutexOverflowTableSize;
+extern mutexHashEntry *firstFreeOverflowEntry;
+
+#define MUTEX_HASH_MASK                  ((MUTEX_HASH_TABLE_SIZE - 1) << 3)
+
+#if 0
+#define MUTEX_HASH_VALUE(a)      ((((long)(a)) & MUTEX_HASH_MASK) >> MUTEX_HASH_TRASH_BITS)
+#else
+#define MUTEX_HASH_VALUE(a)      (( (((long)(a)) ^ ((long)(a) >> MUTEX_HASH_SIGN_BITS)) & mutexHashMask) >> MUTEX_HASH_TRASH_BITS)
+#endif
+#define MUTEX_HASH_SUCCESSOR(h)                  (((h) + 7) & (mutexHashTableSize - 1))
+
+typedef struct _conditionHashEntry
+{
+    java_objectheader *object;
+    iCv condition;
+} conditionHashEntry;
+
+#define CONDITION_HASH_TABLE_SIZE                1024
+
+#define CONDITION_HASH_VALUE(a)                  ((((long)(a)) & conditionHashMask) >> 3)
+#define CONDITION_HASH_SUCCESSOR(h)              (((h) + 7) & (conditionHashTableSize - 1))
+
+typedef struct
+{
+    bool free;
+    java_objectheader *object;
+    iMux mutex;
+    iCv condition;
+} object_mutex;
+
+extern void initLocks (void);
+
+mutexHashEntry* conditionLockedMutexForObject (java_objectheader *object);
+
+void reorderConditionHashTable (int begin);
+iCv* conditionForObject (java_objectheader *object);
+iCv* addConditionForObject (java_objectheader *object);
+void removeConditionForObject (java_objectheader *object);
+
+/*
+ * use these functions only outside critical sections (intsEnable/intsRestore).
+ */
+
+void signal_cond_for_object (java_objectheader *obj);
+void broadcast_cond_for_object (java_objectheader *obj);
+void wait_cond_for_object (java_objectheader *obj, s8 time);
+void lock_mutex_for_object (java_objectheader *obj);
+void unlock_mutex_for_object (java_objectheader *obj);
+
+void lock_mutex (iMux*);
+void unlock_mutex (iMux*);
+void wait_cond (iMux*, iCv*, s8);
+void signal_cond (iCv*);
+void broadcast_cond (iCv*);
+
+/*
+ * use these internal functions only in critical sections. blockInts must be exactly
+ * 1.
+ */
+void internal_lock_mutex (iMux*);
+void internal_unlock_mutex (iMux*);
+void internal_wait_cond (iMux*, iCv*, s8);
+void internal_signal_cond (iCv*);
+void internal_broadcast_cond (iCv*);
+
+void internal_lock_mutex_for_object (java_objectheader *obj);
+void internal_unlock_mutex_for_object (java_objectheader *obj);
+void internal_broadcast_cond_for_object (java_objectheader *obj);
+
+#endif
+
+#endif /* USE_THREADS */
+
+#endif /* __locks_h */
diff --git a/src/threads/green/threadio.c b/src/threads/green/threadio.c
new file mode 100644 (file)
index 0000000..e538b40
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * threadCalls.c
+ * Support for threaded ops which may block (read, write, connect, etc.).
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#define        DBG(s)                    
+
+#include "sysdep/defines.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "thread.h"
+
+/*
+ * We only need this stuff is we are using the internal thread system.
+ */
+#if defined(USE_INTERNAL_THREADS)
+
+#define        TH_READ         0
+#define        TH_WRITE        1
+#define        TH_ACCEPT       TH_READ
+#define        TH_CONNECT      TH_WRITE
+
+static int maxFd;
+static fd_set readsPending;
+static fd_set writesPending;
+static thread* readQ[FD_SETSIZE];
+static thread* writeQ[FD_SETSIZE];
+static struct timeval tm = { 0, 0 };
+
+void blockOnFile(int, int);
+void waitOnEvents(void);
+
+extern thread* currentThread;
+
+/* These are undefined because we do not yet support async I/O */
+#undef F_SETOWN
+#undef FIOSETOWN
+#undef O_ASYNC
+#undef FIOASYNC
+
+/*
+ * Create a threaded file descriptor.
+ */
+int
+threadedFileDescriptor(int fd)
+{
+#if !defined(BLOCKING_CALLS)
+    int r;
+    int on = 1;
+    int pid;
+
+    /* Make non-blocking */
+#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
+    r = fcntl(fd, F_GETFL, 0);
+    r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
+#elif defined(HAVE_IOCTL) && defined(FIONBIO)
+    r = ioctl(fd, FIONBIO, &on);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+
+    /* Allow socket to signal this process when new data is available */
+    pid = getpid();
+#if defined(HAVE_FCNTL) && defined(F_SETOWN)
+    r = fcntl(fd, F_SETOWN, pid);
+#elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
+    r = ioctl(fd, FIOSETOWN, &pid);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+
+#if defined(HAVE_FCNTL) && defined(O_ASYNC)
+    r = fcntl(fd, F_GETFL, 0);
+    r = fcntl(fd, F_SETFL, r|O_ASYNC);
+#elif defined(HAVE_IOCTL) && defined(FIOASYNC)
+    r = ioctl(fd, FIOASYNC, &on);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+#endif
+    return (fd);
+}
+
+/*
+ * Threaded create socket.
+ */
+int
+threadedSocket(int af, int type, int proto)
+{
+    int fd;
+    int r;
+    int on = 1;
+    int pid;
+
+    fd = socket(af, type, proto);
+    return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded file open.
+ */
+int
+threadedOpen(char* path, int flags, int mode)
+{
+    int fd;
+    int r;
+    int on = 1;
+    int pid;
+
+    fd = open(path, flags, mode);
+    return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded socket connect.
+ */
+int
+threadedConnect(int fd, struct sockaddr* addr, int len)
+{
+    int r;
+
+    r = connect(fd, addr, len);
+#if !defined(BLOCKING_CALLS)
+    if ((r < 0)
+       && (errno == EINPROGRESS || errno == EALREADY
+           || errno == EWOULDBLOCK)) {
+       blockOnFile(fd, TH_CONNECT);
+       r = 0; /* Assume it's okay when we get released */
+    }
+#endif
+
+    return (r);
+}
+
+/*
+ * Threaded socket accept.
+ */
+int
+threadedAccept(int fd, struct sockaddr* addr, int* len)
+{
+    int r;
+    int on = 1;
+
+    for (;;)
+    {
+#if defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_ACCEPT);
+#endif
+       r = accept(fd, addr, len);
+       if (r >= 0
+           || !(errno == EINPROGRESS || errno == EALREADY
+                || errno == EWOULDBLOCK))
+       {
+           break;
+       }
+#if !defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_ACCEPT);
+#endif
+    }
+    return (threadedFileDescriptor(r));
+}
+
+/*
+ * Read but only if we can.
+ */
+int
+threadedRead(int fd, char* buf, int len)
+{
+    int r;
+
+    DBG(   printf("threadedRead\n");          )
+
+#if defined(BLOCKING_CALLS)
+    blockOnFile(fd, TH_READ);
+#endif
+    for (;;)
+    {
+       r = read(fd, buf, len);
+       if (r < 0
+           && (errno == EAGAIN || errno == EWOULDBLOCK
+               || errno == EINTR))
+       {
+           blockOnFile(fd, TH_READ);
+           continue;
+       }
+       return (r);
+    }
+}
+
+/*
+ * Write but only if we can.
+ */
+int
+threadedWrite(int fd, char* buf, int len)
+{
+    int r;
+    char* ptr;
+
+    ptr = buf;
+    r = 1;
+
+    DBG(    printf("threadedWrite %dbytes\n",len);      )
+
+    while (len > 0 && r > 0)
+    {
+#if defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_WRITE);
+#endif
+       r = write(fd, ptr, len);
+       if (r < 0
+           && (errno == EAGAIN || errno == EWOULDBLOCK
+               || errno == EINTR))
+       {
+#if !defined(BLOCKING_CALLS)
+           blockOnFile(fd, TH_WRITE);
+#endif
+           r = 1;
+       }
+       else
+       {
+           ptr += r;
+           len -= r;
+       }
+    }
+    return (ptr - buf);
+}
+
+/*
+ * An attempt to access a file would block, so suspend the thread until
+ * it will happen.
+ */
+void
+blockOnFile(int fd, int op)
+{
+DBG(   printf("blockOnFile()\n");                                      )
+
+    intsDisable();
+
+    if (fd > maxFd)
+    {
+       maxFd = fd;
+    }
+    if (op == TH_READ)
+    {
+       FD_SET(fd, &readsPending);
+       suspendOnQThread(currentThread, &readQ[fd]);
+       FD_CLR(fd, &readsPending);
+    }
+    else
+    {
+       FD_SET(fd, &writesPending);
+       suspendOnQThread(currentThread, &writeQ[fd]);
+       FD_CLR(fd, &writesPending);
+    }
+
+    intsRestore();
+}
+
+/*
+ * Check if some file descriptor or other event to become ready.
+ * Block if required (but make sure we can still take timer interrupts).
+ */
+void
+checkEvents(bool block)
+{
+    int r;
+    fd_set rd;
+    fd_set wr;
+    thread* tid;
+    thread* ntid;
+    int i;
+    int b;
+
+DBG(   printf("checkEvents block:%d\n", block);                        )
+
+#if defined(FD_COPY)
+    FD_COPY(&readsPending, &rd);
+    FD_COPY(&writesPending, &wr);
+#else
+    memcpy(&rd, &readsPending, sizeof(rd));
+    memcpy(&wr, &writesPending, sizeof(wr));
+#endif
+
+    /* 
+     * If select() is called with indefinite wait, we have to make sure
+     * we can get interrupted by timer events. 
+     */
+    if (block == true)
+    {
+       b = blockInts;
+       blockInts = 0;
+       r = select(maxFd+1, &rd, &wr, 0, 0);
+       blockInts = b;
+    }
+    else
+    {
+       r = select(maxFd+1, &rd, &wr, 0, &tm);
+    }
+
+    /* We must be holding off interrupts before we start playing with
+     * the read and write queues.  This should be already done but a
+     * quick check never hurt anyone.
+     */
+    assert(blockInts > 0);
+
+DBG(   printf("Select returns %d\n", r);                               )
+
+    for (i = 0; r > 0 && i <= maxFd; i++)
+    {
+       if (readQ[i] != 0 && FD_ISSET(i, &rd))
+       {
+           for (tid = readQ[i]; tid != 0; tid = ntid)
+           {
+               ntid = tid->next;
+               iresumeThread(tid);
+           }
+           readQ[i] = 0;
+           r--;
+       }
+       if (writeQ[i] != 0 && FD_ISSET(i, &wr))
+       {
+           for (tid = writeQ[i]; tid != 0; tid = ntid)
+           {
+               ntid = tid->next;
+               iresumeThread(tid);
+           }
+           writeQ[i] = 0;
+           r--;
+       }
+    }
+}
+#endif
diff --git a/src/threads/green/threadio.h b/src/threads/green/threadio.h
new file mode 100644 (file)
index 0000000..1e9d5c2
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- c -*- */
+
+#ifndef __threadio_h_
+#define __threadio_h_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "../global.h"
+
+#ifdef USE_THREADS
+int threadedFileDescriptor(int fd);
+int threadedSocket(int af, int type, int proto);
+int threadedOpen(char* path, int flags, int mode);
+int threadedConnect(int fd, struct sockaddr* addr, int len);
+int threadedAccept(int fd, struct sockaddr* addr, int* len);
+int threadedRead(int fd, char* buf, int len);
+int threadedWrite(int fd, char* buf, int len);
+#else
+#define threadedFileDescriptor(fd)
+#define threadedRead(fd,buf,len)          read(fd,buf,len)
+#define threadedWrite(fd,buf,len)         write(fd,buf,len)
+#endif
+
+
+#endif
diff --git a/src/threads/green/threads.c b/src/threads/green/threads.c
new file mode 100644 (file)
index 0000000..89dde1d
--- /dev/null
@@ -0,0 +1,681 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * thread.c
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/mman.h>                   /* for mprotect */
+#include <unistd.h>
+
+#include "thread.h"
+#include "locks.h"
+#include "sysdep/defines.h"
+#include "sysdep/threads.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+#include "../builtin.h"
+#include "../asmpart.h"
+
+static classinfo *class_java_lang_ThreadDeath;
+
+#if 1
+#define DBG(s)
+#define SDBG(s)
+#else
+#define DBG(s)                 s
+#define SDBG(s)                s
+#endif
+
+#if defined(USE_INTERNAL_THREADS)
+
+thread* currentThread;
+thread* threadQhead[MAX_THREAD_PRIO + 1];
+thread* threadQtail[MAX_THREAD_PRIO + 1];
+
+thread* liveThreads;
+thread* alarmList;
+
+thread* gcDaemonThread;
+
+int blockInts;
+bool needReschedule;
+
+ctx contexts[MAXTHREADS];
+
+/* Number of threads alive, also counting daemons */
+static int talive;
+
+/* Number of daemon threads alive */
+static int tdaemon;
+
+static void firstStartThread(void);
+
+void reschedule(void);
+
+/* Setup default thread stack size - this can be overwritten if required */
+int threadStackSize = THREADSTACKSIZE;
+
+static thread* startDaemon(void* func, char* nm, int stackSize);
+
+/*
+ * Allocate the stack for a thread
+ */
+void
+allocThreadStack (thread *tid, int size)
+{
+    int pageSize = getpagesize(),
+               result;
+    unsigned long pageBegin;
+
+    CONTEXT(tid).stackMem = malloc(size + 2 * pageSize);
+    assert(CONTEXT(tid).stackMem != 0);
+    CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
+    
+    pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+    pageBegin = pageBegin - pageBegin % pageSize;
+
+    result = mprotect((void*)pageBegin, pageSize, PROT_NONE);
+    assert(result == 0);
+
+    CONTEXT(tid).stackBase = (u1*)pageBegin + pageSize;
+}
+
+/*
+ * Free the stack for a thread
+ */
+void
+freeThreadStack (thread *tid)
+{
+    if (!(CONTEXT(tid).flags & THREAD_FLAGS_NOSTACKALLOC))
+    {
+               int pageSize = getpagesize(),
+                       result;
+               unsigned long pageBegin;
+
+               pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+               pageBegin = pageBegin - pageBegin % pageSize;
+       
+               result = mprotect((void*)pageBegin, pageSize,
+                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
+               assert(result == 0);
+
+               free(CONTEXT(tid).stackMem);
+    }
+    CONTEXT(tid).stackMem = 0;
+    CONTEXT(tid).stackBase = 0;
+    CONTEXT(tid).stackEnd = 0;
+}
+
+/*
+ * Initialize threads.
+ */
+void
+initThreads(u1 *stackbottom)
+{
+    int i;
+
+    initLocks();
+
+    for (i = 0; i < MAXTHREADS; ++i)
+               contexts[i].free = true;
+
+    /* Allocate a thread to be the main thread */
+    currentThread = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+    assert(currentThread != 0);
+    
+    currentThread->PrivateInfo = 1;
+    CONTEXT(currentThread).free = false;
+
+    liveThreads = currentThread;
+
+    currentThread->name = javastring_new(unicode_new_char("main"));
+    currentThread->priority = NORM_THREAD_PRIO;
+    CONTEXT(currentThread).priority = (u1)currentThread->priority;
+    CONTEXT(currentThread).exceptionptr = 0;
+    currentThread->next = 0;
+    CONTEXT(currentThread).status = THREAD_SUSPENDED;
+    CONTEXT(currentThread).stackBase = CONTEXT(currentThread).stackEnd = stackbottom;
+    THREADINFO(&CONTEXT(currentThread));
+
+    DBG( printf("main thread %p base %p end %p\n", 
+                               currentThread, 
+                               CONTEXT(currentThread).stackBase, 
+                               CONTEXT(currentThread).stackEnd); );
+
+       CONTEXT(currentThread).flags = THREAD_FLAGS_NOSTACKALLOC;
+       CONTEXT(currentThread).nextlive = 0;
+       currentThread->single_step = 0;
+       currentThread->daemon = 0;
+       currentThread->stillborn = 0;
+       currentThread->target = 0;
+       currentThread->interruptRequested = 0;
+       currentThread->group =
+               (threadGroup*)builtin_new(loader_load(unicode_new_char("java/lang/ThreadGroup")));
+       /* we should call the constructor */
+       assert(currentThread->group != 0);
+
+       talive++;
+
+       /* Add thread into runQ */
+       iresumeThread(currentThread);
+
+       /* Start garbage collection thread */
+       gcDaemonThread = startDaemon(gc_thread, "gc", 1024*512);
+       iresumeThread(gcDaemonThread);
+
+       heap_addreference((void**)&gcDaemonThread);
+
+       /* Load exception classes */
+       class_java_lang_ThreadDeath = loader_load(unicode_new_char("java/lang/ThreadDeath"));
+
+       DBG( fprintf(stderr, "finishing initThreads\n"); );
+
+       assert(blockInts == 0);
+}
+
+/*
+ * Start a new thread running.
+ */
+void
+startThread (thread* tid)
+{
+    int i;
+
+    /* Allocate a stack context */
+    for (i = 0; i < MAXTHREADS; ++i)
+               if (contexts[i].free)
+                       break;
+
+    if (i == MAXTHREADS)
+               panic("Too many threads");
+
+    tid->PrivateInfo = i + 1;
+    CONTEXT(tid).free = false;
+    CONTEXT(tid).nextlive = liveThreads;
+    liveThreads = tid;
+    allocThreadStack(tid, threadStackSize);
+    CONTEXT(tid).usedStackTop = CONTEXT(tid).stackBase;
+    CONTEXT(tid).flags = THREAD_FLAGS_GENERAL;
+    CONTEXT(tid).status = THREAD_SUSPENDED;
+    CONTEXT(tid).priority = (u1)tid->priority;
+    CONTEXT(tid).exceptionptr = 0;
+
+    /* Construct the initial restore point. */
+    THREADINIT((&CONTEXT(tid)), firstStartThread);
+
+    DBG( printf("new thread %p base %p end %p\n",
+                               tid, CONTEXT(tid).stackBase,
+                               CONTEXT(tid).stackEnd); );
+
+       talive++;
+       if (tid->daemon)
+               tdaemon++;
+
+       /* Add thread into runQ */
+       iresumeThread(tid);
+}
+
+/*
+ * Start a daemon thread.
+ */
+static thread*
+startDaemon(void* func, char* nm, int stackSize)
+{
+    thread* tid;
+    int i;
+
+    DBG( printf("startDaemon %s\n", nm); );
+
+       tid = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+       assert(tid != 0);
+
+       for (i = 0; i < MAXTHREADS; ++i)
+               if (contexts[i].free)
+                       break;
+       if (i == MAXTHREADS)
+               panic("Too many threads");
+
+       tid->PrivateInfo = i + 1;
+       CONTEXT(tid).free = false;
+       tid->name = 0;          /* for the moment */
+       tid->priority = MAX_THREAD_PRIO;
+       CONTEXT(tid).priority = (u1)tid->priority;
+       tid->next = 0;
+       CONTEXT(tid).status = THREAD_SUSPENDED;
+
+       allocThreadStack(tid, stackSize);
+       tid->single_step = 0;
+       tid->daemon = 1;
+       tid->stillborn = 0;
+       tid->target = 0;
+       tid->interruptRequested = 0;
+       tid->group = 0;
+
+       /* Construct the initial restore point. */
+       THREADINIT((&CONTEXT(tid)), func);
+
+       talive++;
+       tdaemon++;
+
+       return tid;
+}
+
+/*
+ * All threads start here.
+ */
+static void
+firstStartThread(void)
+{
+    methodinfo *method;
+
+    DBG( printf("firstStartThread %p\n", currentThread); );
+
+       /* Every thread starts with the interrupts off */
+       intsRestore();
+       assert(blockInts == 0);
+
+       /* Find the run()V method and call it */
+       method = class_findmethod(currentThread->header.vftbl->class,
+                                                         unicode_new_char("run"), unicode_new_char("()V"));
+       if (method == 0)
+               panic("Cannot find method \'void run ()\'");
+       asm_calljavamethod(method, currentThread, NULL, NULL, NULL);
+
+       killThread(0);
+       assert("Thread returned from killThread" == 0);
+}
+
+/*
+ * Resume a thread running.
+ * This routine has to be called only from locations which ensure
+ * run / block queue consistency. There is no check for illegal resume
+ * conditions (like explicitly resuming an IO blocked thread). There also
+ * is no update of any blocking queue. Both has to be done by the caller
+ */
+void
+iresumeThread(thread* tid)
+{
+    DBG( printf("resumeThread %p\n", tid); );
+
+       intsDisable();
+
+       if (CONTEXT(tid).status != THREAD_RUNNING)
+       {
+               CONTEXT(tid).status = THREAD_RUNNING;
+
+               DBG( fprintf(stderr, "prio is %d\n", CONTEXT(tid).priority); );
+
+               /* Place thread on the end of its queue */
+               if (threadQhead[CONTEXT(tid).priority] == 0) {
+                       threadQhead[CONTEXT(tid).priority] = tid;
+                       threadQtail[CONTEXT(tid).priority] = tid;
+                       if (CONTEXT(tid).priority
+                               > CONTEXT(currentThread).priority)
+                               needReschedule = true;
+               }
+               else
+               {
+                       threadQtail[CONTEXT(tid).priority]->next = tid;
+                       threadQtail[CONTEXT(tid).priority] = tid;
+               }
+               tid->next = 0;
+       }
+       SDBG( else { printf("Re-resuming %p\n", tid); } );
+
+       intsRestore();
+}
+
+/*
+ * Yield process to another thread of equal priority.
+ */
+void
+yieldThread()
+{
+    intsDisable();
+
+    if (threadQhead[CONTEXT(currentThread).priority]
+               != threadQtail[CONTEXT(currentThread).priority])
+    {
+               /* Get the next thread and move me to the end */
+               threadQhead[CONTEXT(currentThread).priority] = currentThread->next;
+               threadQtail[CONTEXT(currentThread).priority]->next = currentThread;
+               threadQtail[CONTEXT(currentThread).priority] = currentThread;
+               currentThread->next = 0;
+               needReschedule = true;
+    }
+
+    intsRestore();
+}
+
+/*
+ * Explicit request by user to resume a thread
+ * The definition says that it is just legal to call this after a preceeding
+ * suspend (which got through). If the thread was blocked for some other
+ * reason (either sleep or IO or a muxSem), we simply can't do it
+ * We use a new thread flag THREAD_FLAGS_USER_SUSPEND for this purpose
+ * (which is set by suspendThread(.))
+ */
+void
+resumeThread(thread* tid)
+{
+    if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
+    {
+               intsDisable();
+               CONTEXT(tid).flags &= ~THREAD_FLAGS_USER_SUSPEND;
+               iresumeThread(tid);
+               intsRestore();
+    }
+}
+
+/*
+ * Suspend a thread.
+ * This is an explicit user request to suspend the thread - the counterpart
+ * for resumeThreadRequest(.). It is JUST called by the java method
+ * Thread.suspend()
+ * What makes it distinct is the fact that the suspended thread is not contained
+ * in any block queue. Without a special flag (indicating the user suspend), we
+ * can't check s suspended thread for this condition afterwards (which is
+ * required by resumeThreadRequest()). The new thread flag
+ * THREAD_FLAGS_USER_SUSPEND is used for this purpose.
+ */
+void
+suspendThread(thread* tid)
+{
+    thread** ntid;
+
+    intsDisable();
+
+    if (CONTEXT(tid).status != THREAD_SUSPENDED)
+    {
+               CONTEXT(tid).status = THREAD_SUSPENDED;
+               
+               /*
+                * This is used to indicate the explicit suspend condition
+                * required by resumeThreadRequest()
+                */
+               CONTEXT(tid).flags |= THREAD_FLAGS_USER_SUSPEND;
+
+               for (ntid = &threadQhead[CONTEXT(tid).priority];
+                        *ntid != 0;
+                        ntid = &(*ntid)->next)
+               {
+                       if (*ntid == tid)
+                       {
+                               *ntid = tid->next;
+                               tid->next = 0;
+                               if (tid == currentThread)
+                               {
+                                       reschedule();
+                               }
+                               break;
+                       }
+               }
+    }
+       SDBG( else { printf("Re-suspending %p\n", tid); } );
+
+       intsRestore();
+}
+
+/*
+ * Suspend a thread on a queue.
+ */
+void
+suspendOnQThread(thread* tid, thread** queue)
+{
+    thread** ntid;
+
+       DBG( printf("suspendOnQThread %p %p\n", tid, queue); );
+
+       assert(blockInts == 1);
+
+       if (CONTEXT(tid).status != THREAD_SUSPENDED)
+       {
+               CONTEXT(tid).status = THREAD_SUSPENDED;
+
+               for (ntid = &threadQhead[CONTEXT(tid).priority];
+                        *ntid != 0;
+                        ntid = &(*ntid)->next)
+               {
+                       if (*ntid == tid)
+                       {
+                               *ntid = tid->next;
+                               /* Insert onto head of lock wait Q */
+                               tid->next = *queue;
+                               *queue = tid;
+                               if (tid == currentThread)
+                               {
+                                       DBG( fprintf(stderr, "suspending %p (cur=%p) with prio %d\n",
+                                                                tid, currentThread, CONTEXT(tid).priority); );
+                                       reschedule();
+                               }
+                               break;
+                       }
+               }
+       }
+       SDBG( else { printf("Re-suspending %p on %p\n", tid, *queue); } );
+}
+
+/*
+ * Kill thread.
+ */
+void
+killThread(thread* tid)
+{
+    thread** ntid;
+
+    intsDisable();
+
+    /* A null tid means the current thread */
+    if (tid == 0)
+    {
+               tid = currentThread;
+    }
+
+       DBG( printf("killThread %p\n", tid); );
+
+       if (CONTEXT(tid).status != THREAD_DEAD)
+       {
+               /* Get thread off runq (if it needs it) */
+               if (CONTEXT(tid).status == THREAD_RUNNING)
+               {
+                       for (ntid = &threadQhead[CONTEXT(tid).priority];
+                                *ntid != 0;
+                                ntid = &(*ntid)->next)
+                       {
+                               if (*ntid == tid)
+                               {
+                                       *ntid = tid->next;
+                                       break;
+                               }
+                       }
+               }
+
+               CONTEXT(tid).status = THREAD_DEAD;
+               talive--;
+               if (tid->daemon) {
+                       tdaemon--;
+               }
+
+               /* If we only have daemons left, then everyone is dead. */
+               if (talive == tdaemon) {
+                       /* Am I suppose to close things down nicely ?? */
+                       exit(0);
+               }
+
+               /* Notify on the object just in case anyone is waiting */
+               internal_lock_mutex_for_object(&tid->header);
+               internal_broadcast_cond_for_object(&tid->header);
+               internal_unlock_mutex_for_object(&tid->header);
+
+               /* Remove thread from live list to it can be garbaged */
+               for (ntid = &liveThreads;
+                        *ntid != 0;
+                        ntid = &(CONTEXT((*ntid)).nextlive))
+               {
+                       if (tid == (*ntid))
+                       {
+                               (*ntid) = CONTEXT(tid).nextlive;
+                               break;
+                       }
+               }
+
+               /* Free stack */
+               freeThreadStack(tid);
+
+               /* free context */
+               CONTEXT(tid).free = true;
+
+               /* Run something else */
+               needReschedule = true;
+       }
+       intsRestore();
+}
+
+/*
+ * Change thread priority.
+ */
+void
+setPriorityThread(thread* tid, int prio)
+{
+    thread** ntid;
+
+    if (tid->PrivateInfo == 0) {
+               tid->priority = prio;
+               return;
+    }
+
+    if (CONTEXT(tid).status == THREAD_SUSPENDED) {
+               CONTEXT(tid).priority = (u8)prio;
+               return;
+    }
+
+    intsDisable();
+
+    /* Remove from current thread list */
+    for (ntid = &threadQhead[CONTEXT(tid).priority]; *ntid != 0; ntid = &(*ntid)->next) {
+               if (*ntid == tid) {
+                       *ntid = tid->next;
+                       break;
+               }
+    }
+
+    /* Insert onto a new one */
+    tid->priority = prio;
+    CONTEXT(tid).priority = (u8)tid->priority;
+    if (threadQhead[prio] == 0) {
+               threadQhead[prio] = tid;
+               threadQtail[prio] = tid;
+               if (prio > CONTEXT(currentThread).priority) {
+                       needReschedule = true;
+               }
+    }
+    else {
+               threadQtail[prio]->next = tid;
+               threadQtail[prio] = tid;
+    }
+    tid->next = 0;
+
+    intsRestore();
+}
+
+/*
+ * Is this thread alive?
+ */
+bool
+aliveThread(thread* tid)
+{
+    if (tid->PrivateInfo != 0 && CONTEXT(tid).status != THREAD_DEAD)
+               return (true);
+    else
+               return (false);
+}
+
+/*
+ * Reschedule the thread.
+ * Called whenever a change in the running thread is required.
+ */
+void
+reschedule(void)
+{
+    int i;
+    thread* lastThread;
+    int b;
+    /*    sigset_t nsig; */
+
+    /* A reschedule in a non-blocked context is half way to hell */
+    assert(blockInts > 0);
+    b = blockInts;
+    
+    /* Check events - we may release a high priority thread */
+    /* Just check IO, no need for a reschedule call by checkEvents() */
+    needReschedule = false;
+    checkEvents(false);
+
+    for (;;)
+    {
+               for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--)
+               {
+                       if (threadQhead[i] != 0)
+                       {
+                               DBG( fprintf(stderr, "found thread %p in head %d\n", threadQhead[i], i); );
+
+                               if (threadQhead[i] != currentThread)
+                               {
+                                       USEDSTACKTOP((CONTEXT(currentThread).usedStackTop));
+
+                                       lastThread = currentThread;
+                                       currentThread = threadQhead[i];
+
+                                       CONTEXT(currentThread).exceptionptr = exceptionptr;
+
+                                       THREADSWITCH((&CONTEXT(currentThread)),
+                                                                (&CONTEXT(lastThread)));
+                                       blockInts = b;
+
+                                       exceptionptr = CONTEXT(currentThread).exceptionptr;
+
+                                       /* Alarm signal may be blocked - if so
+                                        * unblock it.
+                                        */
+                                       /*
+                                         if (alarmBlocked == true) {
+                                         alarmBlocked = false;
+                                         sigemptyset(&nsig);
+                                         sigaddset(&nsig, SIGALRM);
+                                         sigprocmask(SIG_UNBLOCK, &nsig, 0);
+                                         }
+                                       */
+
+                                       /* I might be dying */
+                                       if ((CONTEXT(lastThread).flags & THREAD_FLAGS_KILLED)
+                                               != 0)
+                                       {
+                                               CONTEXT(lastThread).flags &= ~THREAD_FLAGS_KILLED;
+                                               exceptionptr = native_new_and_init(class_java_lang_ThreadDeath);
+                                       }
+                               }
+                               /* Now we kill the schedule and turn ints
+                                  back on */
+                               needReschedule = false;
+                               return;
+                       }
+               }
+               /* Nothing to run - wait for external event */
+               DBG( fprintf(stderr, "nothing more to do\n"); );
+               checkEvents(true);
+    }
+}
+
+#endif
diff --git a/src/threads/green/threads.h b/src/threads/green/threads.h
new file mode 100644 (file)
index 0000000..1f72d9e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * thread.h
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __thread_h
+#define __thread_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+
+#define MAXTHREADS              256          /* schani */
+
+#define        THREADCLASS             "java/lang/Thread"
+#define        THREADGROUPCLASS        "java/lang/ThreadGroup"
+#define        THREADDEATHCLASS        "java/lang/ThreadDeath"
+
+#define        MIN_THREAD_PRIO         1
+#define        NORM_THREAD_PRIO        5
+#define        MAX_THREAD_PRIO         10
+
+#define        THREAD_SUSPENDED        0
+#define        THREAD_RUNNING          1
+#define        THREAD_DEAD             2
+#define        THREAD_KILL             3
+
+#define        THREAD_FLAGS_GENERAL            0
+#define        THREAD_FLAGS_NOSTACKALLOC       1
+#define THREAD_FLAGS_USER_SUSPEND       2  /* Flag explicit suspend() call */
+#define        THREAD_FLAGS_KILLED             4
+
+struct _thread;
+
+typedef struct _ctx
+{
+    bool               free;           /* schani */
+    u1                 status;
+    u1                 priority;
+    u1*                restorePoint;
+    u1*                stackMem;           /* includes guard page */
+    u1*                stackBase;
+    u1*                stackEnd;
+    u1*                usedStackTop;
+    s8                 time;
+    java_objectheader *exceptionptr;
+    struct _thread    *nextlive;
+    u1                 flags;
+} ctx;
+
+/*
+struct _stringClass;
+struct _object;
+*/
+
+/* This structure mirrors java.lang.ThreadGroup.h */
+
+typedef struct _threadGroup
+{
+    java_objectheader    header;
+    struct _threadGroup* parent;
+    java_objectheader*   name;
+    s4                   maxPrio;
+    s4                   destroyed;
+    s4                   daemon;
+    s4                   nthreads;
+    java_objectheader*   threads;
+    s4                   ngroups;
+    java_objectheader*   groups;
+} threadGroup;
+
+/* This structure mirrors java.lang.Thread.h */
+typedef struct _thread
+{
+    java_objectheader        header;
+    java_objectheader*       name;
+    s4                       priority;
+    struct _thread*          next;
+    s8                       PrivateInfo;
+    struct java_lang_Object* eetop;           /* ??? */
+    s4                       single_step;
+    s4                       daemon;
+    s4                       stillborn;
+    java_objectheader*       target;
+    s4                       interruptRequested;
+    threadGroup*             group;
+} thread;
+
+void initThreads(u1 *stackbottom);
+void startThread(thread*);
+void resumeThread(thread*);
+void iresumeThread(thread*);
+void suspendThread(thread*);
+void suspendOnQThread(thread*, thread**);
+void yieldThread(void);
+void killThread(thread*);
+void setPriorityThread(thread*, int);
+
+void sleepThread(s8);
+bool aliveThread(thread*);
+long framesThread(thread*);
+
+void reschedule(void);
+
+void checkEvents(bool block);
+
+extern int blockInts;
+extern bool needReschedule;
+extern thread *currentThread;
+extern ctx contexts[];
+extern int threadStackSize;
+
+extern thread *liveThreads;
+
+extern thread *threadQhead[MAX_THREAD_PRIO + 1];
+
+#define CONTEXT(_t)                                                     \
+        (contexts[(_t)->PrivateInfo - 1])
+
+#if 1
+#define        intsDisable()   blockInts++
+#define        intsRestore()   if (blockInts == 1 && needReschedule) {         \
+                           reschedule();                               \
+                       }                                               \
+                       blockInts--
+#else
+#define        intsDisable()   do { blockInts++; fprintf(stderr, "++: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); } while (0)
+#define        intsRestore()   do { \
+                            if (blockInts == 1 && needReschedule) {    \
+                               reschedule();                           \
+                           }                                           \
+                           blockInts--;                                \
+                            fprintf(stderr, "--: %d (%s:%d)\n", blockInts, __FILE__, __LINE__);     \
+                        } while (0)
+#endif
+
+#else
+
+#define intsDisable()
+#define intsRestore()
+
+#endif
+
+#endif
diff --git a/src/toolbox/chain.c b/src/toolbox/chain.c
new file mode 100644 (file)
index 0000000..7e50617
--- /dev/null
@@ -0,0 +1,243 @@
+/************************* toolbox/chain.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see chain.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "chain.h"
+
+
+
+chain *chain_new ()
+{
+       chain *c;
+       
+       c = NEW (chain);
+       c -> usedump = 0;
+       c -> first = NULL;
+       c -> last = NULL;
+       c -> active = NULL;
+
+       return c;
+}
+
+chain *chain_dnew ()
+{
+       chain *c;
+       
+       c = DNEW (chain);
+       c -> usedump = 1;
+       c -> first = NULL;
+       c -> last = NULL;
+       c -> active = NULL;
+
+       return c;
+}
+
+
+void chain_free (chain *c)
+{
+       chainlink *l;
+
+       assert (! c->usedump);
+
+       l = c->first;
+       while (l) {
+               chainlink *nextl = l->next;
+               
+               FREE (l, chainlink);
+               l = nextl;      
+               }
+       
+       FREE (c, chain);
+}
+
+
+void chain_addafter(chain *c, void *element)
+{
+       chainlink *active,*newlink;
+
+    active = c->active;
+
+       if (c -> usedump) newlink = DNEW (chainlink);
+       else              newlink = NEW (chainlink);
+
+       newlink -> element = element;
+       
+       if (active) {
+               newlink -> next = active -> next;
+               newlink -> prev = active;
+               
+               active -> next = newlink;
+               if (newlink -> next) newlink -> next -> prev = newlink;
+                               else c -> last = newlink;
+               }
+       else {  
+               newlink -> next = NULL;
+               newlink -> prev = NULL;
+
+               c -> active = newlink;  
+               c -> first = newlink;
+               c -> last = newlink;
+               }
+}
+
+
+void chain_addbefore(chain *c, void *element)
+{
+       chainlink *active,*newlink;
+
+    active = c->active;
+
+       if (c -> usedump) newlink = DNEW (chainlink);
+       else              newlink = NEW (chainlink);
+       
+       newlink -> element = element;
+       
+       if (active) {
+               newlink -> next = active;
+               newlink -> prev = active -> prev;
+               
+               active -> prev = newlink;
+               if (newlink -> prev) newlink -> prev -> next = newlink;
+               else                 c -> first = newlink;
+               }
+       else {  
+               newlink -> next = NULL;
+               newlink -> prev = NULL;
+
+               c -> active = newlink;  
+               c -> first = newlink;
+               c -> last = newlink;
+               }
+}
+
+void chain_addlast (chain *c, void *e)
+{
+       chain_last (c);
+       chain_addafter (c, e);
+}
+
+void chain_addfirst (chain *c, void *e)
+{
+       chain_first (c);
+       chain_addbefore (c, e);
+}
+
+
+void chain_remove (chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       assert (active);
+
+       if (active -> next) {
+               active -> next -> prev = active -> prev;
+               }
+       else {
+               c -> last = active -> prev;
+               }
+       
+       if (active -> prev) {
+               active -> prev -> next = active -> next;
+               }
+       else {
+               c -> first = active -> next;
+               }
+
+
+       if (active->prev) 
+               c -> active = active->prev;
+       else
+               c -> active = active->next;
+
+       if (! c -> usedump) FREE (active, chainlink);
+}
+
+
+void *chain_remove_go_prev (chain *c)
+{
+       chain_remove (c);
+       return chain_this (c);
+}
+
+
+
+void chain_removespecific(chain *c, void *e)
+{
+       void *ce;
+       
+       ce = chain_first (c);
+       while (ce) {
+               if (e == ce) { chain_remove (c); return; }
+        ce = chain_next (c);           
+               }
+               
+}
+
+void *chain_next(chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       if (!active) return NULL;
+       
+       if (active -> next) {
+               c -> active = active -> next;
+               return c -> active -> element;
+               }
+               
+       return NULL;
+}
+
+void *chain_prev(chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       if (!active) return NULL;
+       
+       if (active -> prev) {
+               c -> active = active -> prev;
+               return c -> active -> element;
+               }
+
+       return NULL;
+}
+
+
+void *chain_this(chain *c)
+{
+       if (c -> active) return c -> active -> element;
+       return NULL;
+}
+
+
+void *chain_first(chain *c)
+{
+       c -> active = c -> first;
+       if (c -> active) return c -> active -> element;
+       return NULL;
+}
+
+void *chain_last(chain *c)
+{
+       c -> active = c -> last;
+       if (c -> active) return c -> active -> element;;
+       return NULL;
+}
+
diff --git a/src/toolbox/chain.h b/src/toolbox/chain.h
new file mode 100644 (file)
index 0000000..e065c07
--- /dev/null
@@ -0,0 +1,92 @@
+/************************* toolbox/chain.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       dient zur Verwaltung doppelt verketteter Listen mit externer Verkettung
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct chainlink {          /* Struktur f"ur ein Listenelement */
+       struct chainlink *next,*prev;
+       void *element;
+       } chainlink;
+
+typedef struct chain {             /* Struktur f"ur eine Liste */
+       int  usedump;   
+
+       chainlink *first,*last;
+       chainlink *active;
+       } chain;
+
+
+chain *chain_new ();
+chain *chain_dnew ();
+void chain_free(chain *c);
+
+void chain_addafter(chain *c, void *element);
+void chain_addbefore(chain *c, void *element);
+void chain_addlast (chain *c, void *element);
+void chain_addfirst (chain *c, void *element);
+
+void chain_remove(chain *c);
+void *chain_remove_go_prev(chain *c);
+void chain_removespecific(chain *c, void *element);
+
+void *chain_next(chain *c);
+void *chain_prev(chain *c);
+void *chain_this(chain *c);
+
+void *chain_first(chain *c);
+void *chain_last(chain *c);
+
+
+/*
+--------------------------- Schnittstellenbeschreibung ------------------------
+
+Bei Verwendung dieser Funktionen f"ur die Listenverwaltung mu"s, im
+Gegenstatz zum Modul 'list', keine zus"atzliche Vorbereitung in den 
+Element-Strukturen gemacht werden.
+
+Diese Funktionen sind daher auch ein wenig langsamer und brauchen 
+mehr Speicher.
+
+Eine neue Liste wird mit 
+                 chain_new
+       oder  chain_dnew 
+angelegt. Der Unterschied ist, da"s bei der zweiten Variante alle
+zus"atzlichen Datenstrukturen am DUMP-Speicher angelegt werden (was
+schneller geht, und ein explizites Freigeben am Ende der Verarbeitung
+unn"otig macht). Dabei mu"s man aber achtgeben, da"s man nicht 
+versehentlich Teile dieser Strukturen durch ein verfr"uhtes 'dump_release'
+freigibt.
+
+Eine nicht mehr verwendete Liste kann mit
+               chain_free
+freigegeben werden (nur verwenden, wenn mit 'chain_new' angefordert)
+
+
+Das Eintragen neuer Elemente geht sehr einfach mit:
+       chain_addafter, chain_addlast, chain_addbefore, chain_addfirst          
+       
+Durchsuchen der Liste mit:
+       chain_first, chain_last, chain_prev, chain_next, chain_this
+       
+L"oschen von Elementen aus der Liste:
+       chain_remove, chain_remove_go_prev, chain_removespecific
+       
+       
+ACHTUNG: In den zu verkettenden Elementen gibt es ja (wie oben gesagt) keine
+       Referenzen auf die Liste oder irgendwelche Listenknoten, deshalb k"onnen
+       die Elemente nicht als Ortsangabe innerhalb der Liste fungieren.
+       Es gibt vielmehr ein Art 'Cursor', der ein Element als das gerade
+       aktuelle festh"alt, und alle Ein-/und Ausf"ugeoperationen geschehen
+       relativ zu diesem Cursor.
+
+*/
+
diff --git a/src/toolbox/list.c b/src/toolbox/list.c
new file mode 100644 (file)
index 0000000..6183684
--- /dev/null
@@ -0,0 +1,107 @@
+/************************** toolbox/list.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see chain.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "list.h"
+
+
+void list_init (list *l, int nodeoffset)
+{
+       l->first = NULL;
+       l->last = NULL;
+       l->nodeoffset = nodeoffset;
+}
+
+void list_addlast (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+       if (l->last) {
+               n->prev = l->last;
+               n->next = NULL;
+               l->last->next = n;
+               l->last = n;
+               }
+       else {
+               n->prev = NULL;
+               n->next = NULL;
+               l->last = n;
+               l->first = n;
+               }
+}
+
+void list_addfirst (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+       if (l->first) {
+               n->prev = NULL;
+               n->next = l->first;
+               l->first->prev = n;
+               l->first = n;
+               }
+       else {
+               n->prev = NULL;
+               n->next = NULL;
+               l->last = n;
+               l->first = n;
+               }
+}
+
+
+void list_remove (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       
+       if (n->next) n->next->prev = n->prev;
+               else l->last = n->prev;
+       if (n->prev) n->prev->next = n->next;
+               else l->first = n->next;
+}
+
+void *list_first (list *l)
+{
+       if (!l->first) return NULL;
+       return ((char*) l->first) - l->nodeoffset;
+}
+
+
+void *list_last (list *l)
+{
+       if (!l->last) return NULL;
+       return ((char*) l->last) - l->nodeoffset;
+}
+
+
+void *list_next (list *l, void *element)
+{
+       listnode *n;
+       n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       if (!n->next) return NULL;
+       return ((char*) n->next) - l->nodeoffset;
+}
+
+       
+void *list_prev (list *l, void *element)
+{
+       listnode *n;
+       n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       if (!n->prev) return NULL;
+       return ((char*) n->prev) - l->nodeoffset;
+}
+
diff --git a/src/toolbox/list.h b/src/toolbox/list.h
new file mode 100644 (file)
index 0000000..22f7ec0
--- /dev/null
@@ -0,0 +1,97 @@
+/************************** toolbox/list.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Verwaltung von doppelt verketteten Listen. 
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct listnode {           /* Struktur f"ur ein Listenelement */
+       struct listnode *next,*prev;
+       } listnode;
+
+typedef struct list {               /* Struktur f"ur den Listenkopf */
+       listnode *first,*last;
+       int nodeoffset;
+       } list;
+
+
+void list_init (list *l, int nodeoffset);
+
+void list_addlast (list *l, void *element);
+void list_addfirst (list *l, void *element);
+
+void list_remove (list *l, void *element);
+void *list_first (list *l);
+void *list_last (list *l);
+
+void *list_next (list *l, void *element);
+void *list_prev (list *l, void *element);
+
+
+/*
+---------------------- Schnittstellenbeschreibung -----------------------------
+
+Die Listenverwaltung mit diesem Modul geht so vor sich:
+       
+       - jede Struktur, die in die Liste eingeh"angt werden soll, mu"s 
+         eine Komponente vom Typ 'listnode' haben.
+         
+       - es mu"s ein Struktur vom Typ 'list' bereitgestellt werden.
+       
+       - die Funktion list_init (l, nodeoffset) initialisiert diese Struktur,
+         dabei gibt der nodeoffset den Offset der 'listnode'-Komponente in
+         den Knotenstrukturen an.
+         
+       - Einf"ugen, Aush"angen und Suchen von Elementen der Liste geht mit
+         den "ubrigen Funktionen.
+         
+Zum besseren Verst"andnis ein kleines Beispiel:
+
+
+       void bsp() {
+               struct node {
+                       listnode linkage;
+                       int value;
+                       } a,b,c, *el;
+                       
+               list l;
+               
+               a.value = 7;
+               b.value = 9;
+               c.value = 11;
+               
+               list_init (&l, OFFSET(struct node,linkage) );
+               list_addlast (&l, a);
+               list_addlast (&l, b);
+               list_addlast (&l, c);
+               
+               e = list_first (&l);
+               while (e) {
+                       printf ("Element: %d\n", e->value);
+                       e = list_next (&l,e);
+                       }
+       }
+       
+       
+       Dieses Programm w"urde also folgendes ausgeben:
+               7
+               9
+               11
+
+
+
+Der Grund, warum beim Initialisieren der Liste der Offset mitangegeben
+werden mu"s, ist der da"s ein und das selbe Datenelement gleichzeitig
+in verschiedenen Listen eingeh"angt werden kann (f"ur jede Liste mu"s
+also eine Komponente vom Typ 'listnode' im Element enthalten sein).
+
+*/
+
diff --git a/src/toolbox/tree.c b/src/toolbox/tree.c
new file mode 100644 (file)
index 0000000..ae74ffc
--- /dev/null
@@ -0,0 +1,166 @@
+/************************** toolbox/tree.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see tree.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "tree.h"
+
+
+tree *tree_new (treeelementcomperator comperator)
+{
+       tree *t = NEW (tree);
+       
+       t -> usedump = 0;
+       t -> comperator = comperator;
+       t -> top = NULL;
+       t -> active = NULL;
+               
+       return t;
+}
+
+tree *tree_dnew (treeelementcomperator comperator)
+{
+       tree *t = DNEW (tree);
+       
+       t -> usedump = 1;
+       t -> comperator = comperator;
+       t -> top = NULL;
+       t -> active = NULL;
+       
+       return t;
+}
+
+
+static void tree_nodefree (treenode *tn)
+{
+       if (!tn) return;
+       tree_nodefree (tn -> left);
+       tree_nodefree (tn -> right);
+       FREE (tn, treenode);
+}
+
+void tree_free (tree *t)
+{
+       assert (! t -> usedump);
+       
+       tree_nodefree ( t -> top );
+       FREE (t, tree);
+}
+
+
+static treenode *tree_nodeadd 
+    (tree *t, treenode *par, treenode *n, void *element, void *key)
+{
+       if (!n) {
+               if ( t-> usedump )  n = DNEW (treenode);
+               else                n = NEW (treenode);
+               
+               n -> left = NULL;
+               n -> right = NULL;
+               n -> parent = par;
+               n -> element = element;
+               }
+       else {
+               if ( t->comperator (key, n -> element) < 0 ) {
+                       n -> left = tree_nodeadd (t, n, n -> left, element, key);
+                       }
+               else {
+                       n -> right = tree_nodeadd (t, n, n -> right, element, key);
+                       }
+               }
+               
+       return n;
+}
+
+void tree_add (tree *t, void *element, void *key)
+{
+       t -> top = tree_nodeadd (t, NULL, t -> top, element, key);
+       t -> active = t -> top;
+}
+
+
+static treenode *tree_nodefind (tree *t, treenode *n, void *key)
+{
+       int way;
+
+       if (!n) return NULL;
+
+       way = t -> comperator (key, n->element);
+       if (way==0) return n;
+       if (way<0) return tree_nodefind (t, n -> left, key);
+       else       return tree_nodefind (t, n -> right, key);
+}
+
+
+void *tree_find (tree *t, void *key)
+{
+       treenode *tn = tree_nodefind (t, t -> top, key);
+       if (!tn) return NULL;
+
+       t -> active = tn;
+       return tn -> element;
+}
+
+
+
+void *tree_this (tree *t)
+{      
+       if (! t->active) return NULL;
+       return t->active->element;
+}
+
+
+static treenode *leftmostnode(treenode *t)
+{
+       while (t->left) t=t->left;
+       return t;
+}
+
+void *tree_first (tree *t)
+{
+       treenode *a = t->top;
+       if (!a) return NULL;
+
+       a = leftmostnode (a);
+       t->active = a;
+       return a->element;
+}
+
+void *tree_next (tree *t)
+{
+       treenode *a = t->active;
+       treenode *comefrom = NULL;
+
+       while (a) {
+               if (!a) return NULL;
+
+               if (a->left && (a->left == comefrom)) {
+                       t -> active = a;
+                       return a->element;
+                       }
+       
+               if (a->right && (a->right != comefrom) ) {
+                       a = leftmostnode(a->right);
+                       t -> active = a;
+                       return a->element;
+                       }
+               
+               comefrom=a;
+               a=a->parent;
+               }
+       t->active = NULL;
+       return NULL;
+}
diff --git a/src/toolbox/tree.h b/src/toolbox/tree.h
new file mode 100644 (file)
index 0000000..fa974bb
--- /dev/null
@@ -0,0 +1,45 @@
+/************************* toolbox/tree.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Verwaltung bin"arer B"aume 
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef int (*treeelementcomperator) (void *key, void * element);
+
+
+typedef struct treenode {
+       struct treenode *left,*right;
+       struct treenode *parent;
+       
+       void *element;
+       } treenode;
+
+typedef struct {
+       int usedump;
+       treeelementcomperator comperator;       
+
+       treenode *top;
+       treenode *active;
+       } tree;
+
+
+
+tree *tree_new (treeelementcomperator comperator);
+tree *tree_dnew (treeelementcomperator comperator);
+void tree_free (tree *t);
+
+void tree_add (tree *t, void *element, void *key);
+void *tree_find (tree *t, void *key);
+
+void *tree_this (tree *t);
+void *tree_first (tree *t);
+void *tree_next (tree *t);
+
diff --git a/src/vm/builtin.c b/src/vm/builtin.c
new file mode 100644 (file)
index 0000000..c1de52d
--- /dev/null
@@ -0,0 +1,1621 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** builtin.c **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enthaelt die C-Funktionen fuer alle JavaVM-Befehle, die sich nicht direkt
+       auf Maschinencode "ubersetzen lassen. Im Code f"ur die Methoden steht
+       dann ein Funktionsaufruf (nat"urlich mit den Aufrufskonventionen von C).
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/12/03
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <values.h>
+
+#include "global.h"
+#include "builtin.h"
+
+#include "loader.h"
+#include "tables.h"
+
+#include "threads/thread.h"
+#include "threads/locks.h"              /* schani */
+
+#include "sysdep/native-math.h"
+
+builtin_descriptor builtin_desc[] = {
+       {(functionptr) builtin_instanceof,         "instanceof"},
+       {(functionptr) builtin_checkcast,          "checkcast"},
+       {(functionptr) new_builtin_checkcast,      "checkcast"},
+       {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
+       {(functionptr) builtin_checkarraycast,     "checkarraycast"},
+       {(functionptr) new_builtin_checkarraycast, "checkarraycast"},
+       {(functionptr) new_builtin_aastore,        "aastore"},
+       {(functionptr) builtin_new,                "new"},
+       {(functionptr) builtin_anewarray,          "anewarray"},
+       {(functionptr) builtin_newarray_array,     "newarray_array"},
+       {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
+       {(functionptr) builtin_newarray_char,      "newarray_char"},
+       {(functionptr) builtin_newarray_float,     "newarray_float"},
+       {(functionptr) builtin_newarray_double,    "newarray_double"},
+       {(functionptr) builtin_newarray_byte,      "newarray_byte"},
+       {(functionptr) builtin_newarray_short,     "newarray_short"},
+       {(functionptr) builtin_newarray_int,       "newarray_int"},
+       {(functionptr) builtin_newarray_long,      "newarray_long"},
+       {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
+       {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
+       {(functionptr) builtin_monitorenter,       "monitorenter"},
+       {(functionptr) new_builtin_monitorenter,   "monitorenter"},
+       {(functionptr) builtin_monitorexit,        "monitorexit"},
+       {(functionptr) new_builtin_monitorexit,    "monitorexit"},
+       {(functionptr) builtin_idiv,               "idiv"},
+       {(functionptr) new_builtin_idiv,           "idiv"},
+       {(functionptr) builtin_irem,               "irem"},
+       {(functionptr) new_builtin_irem,           "irem"},
+       {(functionptr) builtin_ladd,               "ladd"},
+       {(functionptr) builtin_lsub,               "lsub"},
+       {(functionptr) builtin_lmul,               "lmul"},
+       {(functionptr) builtin_ldiv,               "ldiv"},
+       {(functionptr) new_builtin_ldiv,           "ldiv"},
+       {(functionptr) builtin_lrem,               "lrem"},
+       {(functionptr) new_builtin_lrem,           "lrem"},
+       {(functionptr) builtin_lshl,               "lshl"},
+       {(functionptr) builtin_lshr,               "lshr"},
+       {(functionptr) builtin_lushr,              "lushr"},
+       {(functionptr) builtin_land,               "land"},
+       {(functionptr) builtin_lor,                "lor"},
+       {(functionptr) builtin_lxor,               "lxor"},
+       {(functionptr) builtin_lneg,               "lneg"},
+       {(functionptr) builtin_lcmp,               "lcmp"},
+       {(functionptr) builtin_fadd,               "fadd"},
+       {(functionptr) builtin_fsub,               "fsub"},
+       {(functionptr) builtin_fmul,               "fmul"},
+       {(functionptr) builtin_fdiv,               "fdiv"},
+       {(functionptr) builtin_frem,               "frem"},
+       {(functionptr) builtin_fneg,               "fneg"},
+       {(functionptr) builtin_fcmpl,              "fcmpl"},
+       {(functionptr) builtin_fcmpg,              "fcmpg"},
+       {(functionptr) builtin_dadd,               "dadd"},
+       {(functionptr) builtin_dsub,               "dsub"},
+       {(functionptr) builtin_dmul,               "dmul"},
+       {(functionptr) builtin_ddiv,               "ddiv"},
+       {(functionptr) builtin_drem,               "drem"},
+       {(functionptr) builtin_dneg,               "dneg"},
+       {(functionptr) builtin_dcmpl,              "dcmpl"},
+       {(functionptr) builtin_dcmpg,              "dcmpg"},
+       {(functionptr) builtin_i2l,                "i2l"},
+       {(functionptr) builtin_i2f,                "i2f"},
+       {(functionptr) builtin_i2d,                "i2d"},
+       {(functionptr) builtin_l2i,                "l2i"},
+       {(functionptr) builtin_l2f,                "l2f"},
+       {(functionptr) builtin_l2d,                "l2d"},
+       {(functionptr) builtin_f2i,                "f2i"},
+       {(functionptr) builtin_f2l,                "f2l"},
+       {(functionptr) builtin_f2d,                "f2d"},
+       {(functionptr) builtin_d2i,                "d2i"},
+       {(functionptr) builtin_d2l,                "d2l"},
+       {(functionptr) builtin_d2f,                "d2f"},
+       {(functionptr) NULL,                       "unknown"}
+       };
+
+
+/*****************************************************************************
+                                TYPCHECKS
+*****************************************************************************/
+
+
+
+/*************** interne Funktion: builtin_isanysubclass *********************
+
+       "uberpr"uft, ob eine Klasse eine Unterklasse einer anderen Klasse ist.
+       Dabei gelten auch Interfaces, die eine Klasse implementiert, als
+       deren Oberklassen. 
+       R"uckgabewert:  1 ... es trifft zu
+                       0 ... es trifft nicht zu
+                       
+*****************************************************************************/                 
+
+static s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+{
+       if (super->flags & ACC_INTERFACE) {
+               u4 index = super->index;
+/*             if (sub->vftbl == NULL) return 0; */
+               if (index >= sub->vftbl->interfacetablelength) return 0;
+               return ( sub->vftbl->interfacevftbl[index] ) ? 1 : 0;
+               }
+       else {
+               while (sub) {
+                       if (sub==super) return 1;
+                       sub = sub->super;
+                       }
+               return 0;
+               }
+}
+
+
+/****************** Funktion: builtin_instanceof *****************************
+
+       "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+       abgeleiteten Klasse) ist, oder ob die Klasse des Objekts ein Interface 
+       implementiert.
+       Return:   1, wenn ja
+                 0, wenn nicht, oder wenn Objekt ein NULL-Zeiger
+                
+*****************************************************************************/
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+       log_text ("builtin_instanceof called");
+#endif
+       
+       if (!obj) return 0;
+       return builtin_isanysubclass (obj->vftbl->class, class);
+}
+
+
+
+/**************** Funktion: builtin_checkcast *******************************
+
+       "Uberpr"uft, ob ein Objekt eine Instanz einer Klasse (oder einer davon
+       abgeleiteten Klasse ist).
+       Unterschied zu builtin_instanceof: Ein NULL-Zeiger ist immer richtig
+       Return:   1, wenn ja, oder wenn Objekt ein NULL-Zeiger 
+              0, wenn nicht
+              
+****************************************************************************/
+
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
+{
+#ifdef DEBUG
+       log_text ("builtin_checkcast called");
+#endif
+
+       if (!obj) return 1;
+       if ( builtin_isanysubclass (obj->vftbl->class, class) ) {
+               return 1;
+                               }
+#if DEBUG
+               printf ("#### checkcast failed ");
+               unicode_display (obj->vftbl->class->name);
+               printf (" -> ");
+               unicode_display (class->name);
+               printf ("\n");
+#endif
+               
+       return 0;
+}
+
+
+
+/*********** interne Funktion: builtin_descriptorscompatible ******************
+
+       "uberpr"uft, ob zwei Array-Typdescriptoren compartible sind, d.h.,
+       ob ein Array vom Typ 'desc' gefahrlos einer Variblen vom Typ 'target'
+       zugewiesen werden kann.
+       Return: 1, wenn ja
+               0, wenn nicht
+               
+******************************************************************************/
+
+static s4 builtin_descriptorscompatible
+       (constant_arraydescriptor *desc, constant_arraydescriptor *target)
+{
+       if (desc==target) return 1;
+       if (desc->arraytype != target->arraytype) return 0;
+       switch (target->arraytype) {
+               case ARRAYTYPE_OBJECT: 
+                       return builtin_isanysubclass (desc->objectclass, target->objectclass);
+               case ARRAYTYPE_ARRAY:
+                       return builtin_descriptorscompatible 
+                         (desc->elementdescriptor, target->elementdescriptor);
+               default: return 1;
+               }
+}
+
+
+
+/******************** Funktion: builtin_checkarraycast ***********************
+
+       "uberpr"uft, ob ein gegebenes Objekt tats"achlich von einem 
+       Untertyp des geforderten Arraytyps ist.
+       Dazu muss das Objekt auf jeden Fall ein Array sein. 
+       Bei einfachen Arrays (int,short,double,etc.) muss der Typ genau 
+       "ubereinstimmen.
+       Bei Arrays von Objekten muss der Elementtyp des tats"achlichen Arrays
+       ein Untertyp (oder der selbe Typ) vom geforderten Elementtyp sein.
+       Bei Arrays vom Arrays (die eventuell wieder Arrays von Arrays
+       sein k"onnen) m"ussen die untersten Elementtypen in der entsprechenden
+       Unterklassenrelation stehen.
+
+       Return: 1, wenn Cast in Ordung ist
+                       0, wenn es nicht geht
+       
+       Achtung: ein Cast mit einem NULL-Zeiger geht immer gut.
+                       
+*****************************************************************************/
+
+s4 builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *desc)
+{
+       java_arrayheader *a = (java_arrayheader*) o;
+
+       if (!o) return 1;
+       if (o->vftbl->class != class_array) {
+               return 0;
+               }
+               
+       if (a->arraytype != desc->arraytype) {
+               return 0;
+               }
+       
+       switch (a->arraytype) {
+               case ARRAYTYPE_OBJECT: {
+                       java_objectarray *oa = (java_objectarray*) o;
+                       return builtin_isanysubclass (oa->elementtype, desc->objectclass);
+                       }
+               case ARRAYTYPE_ARRAY: {
+                       java_arrayarray *aa = (java_arrayarray*) o;
+                       return builtin_descriptorscompatible
+                          (aa->elementdescriptor, desc->elementdescriptor);
+                       }
+               default:   
+                       return 1;
+               }
+}
+
+
+s4 builtin_arrayinstanceof
+       (java_objectheader *obj, constant_arraydescriptor *desc)
+{
+       if (!obj) return 1;
+       return builtin_checkarraycast (obj, desc);
+}
+
+
+/************************** exception functions *******************************
+
+******************************************************************************/
+
+java_objectheader *builtin_throw_exception (java_objectheader *exceptionptr) {
+       unicode_display (exceptionptr->vftbl->class->name);
+       printf ("\n");
+       fflush (stdout);
+       return exceptionptr;
+}
+
+
+/******************* Funktion: builtin_canstore *******************************
+
+       "uberpr"uft, ob ein Objekt in einem Array gespeichert werden 
+       darf.
+       Return: 1, wenn es geht
+                       0, wenn nicht
+
+******************************************************************************/
+
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
+{
+       if (!o) return 1;
+       
+       switch (a->header.arraytype) {
+       case ARRAYTYPE_OBJECT:
+               if ( ! builtin_checkcast (o, a->elementtype) ) {
+                       return 0;
+                       }
+               return 1;
+               break;
+
+       case ARRAYTYPE_ARRAY:
+               if ( ! builtin_checkarraycast 
+                        (o, ((java_arrayarray*)a)->elementdescriptor) ) {
+                       return 0;
+                       }
+               return 1;
+               break;
+
+       default:
+               panic ("builtin_canstore called with invalid arraytype");
+               return 0;
+       }
+}
+
+
+
+/*****************************************************************************
+                          ARRAYOPERATIONEN
+*****************************************************************************/
+
+
+
+/******************** Funktion: builtin_new **********************************
+
+       Legt ein neues Objekt einer Klasse am Heap an.
+       Return: Der Zeiger auf das Objekt, oder NULL, wenn kein Speicher
+                       mehr frei ist.
+                       
+*****************************************************************************/
+
+java_objectheader *builtin_new (classinfo *c)
+{
+       java_objectheader *o;
+       
+       o = heap_allocate ( c->instancesize, true, c->finalizer );
+       if (!o) return NULL;
+       
+       memset (o, 0, c->instancesize);
+
+       o -> vftbl = c -> vftbl;
+       return o;
+}
+
+
+
+/******************** Funktion: builtin_anewarray ****************************
+
+       Legt ein Array von Zeigern auf Objekte am Heap an.
+       Parameter: 
+               size ......... Anzahl der Elemente
+               elementtype .. ein Zeiger auf die classinfo-Struktur des Typs
+                              der Elemente
+
+       Return: Zeiger auf das Array, oder NULL (wenn kein Speicher frei)
+
+*****************************************************************************/
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype)
+{
+       s4 i;
+       java_objectarray *a;
+       
+       a = heap_allocate ( sizeof(java_objectarray) + (size-1) * sizeof(void*), 
+                           true, 0 /* FALSE */ );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_OBJECT;
+       a -> elementtype = elementtype;
+       for (i=0; i<size; i++) a->data[i] = NULL;
+       return a;
+}
+
+
+
+/******************** Funktion: builtin_newarray_array ***********************
+
+       Legt ein Array von Zeigern auf Arrays am Heap an.
+       Paramter: size ......... Anzahl der Elemente
+                 elementdesc .. Zeiger auf die Arraybeschreibungs-Struktur f"ur
+                                die Element-Arrays.
+
+       Return: Zeiger auf das Array, oder NULL
+
+*****************************************************************************/
+
+java_arrayarray *builtin_newarray_array 
+        (s4 size, constant_arraydescriptor *elementdesc)
+{
+       s4 i;
+       java_arrayarray *a;
+       
+       a = heap_allocate ( sizeof(java_arrayarray) + (size-1) * sizeof(void*), 
+                           true, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_ARRAY;
+       a -> elementdescriptor = elementdesc;
+       for (i=0; i<size; i++) a->data[i] = NULL;
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_boolean ************************
+
+       Legt ein Array von Bytes am Heap an, das allerdings als Boolean-Array 
+       gekennzeichnet wird (wichtig bei Casts!)
+
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_booleanarray *builtin_newarray_boolean (s4 size)
+{
+       java_booleanarray *a;
+       
+       a = heap_allocate ( sizeof(java_booleanarray) + (size-1) * sizeof(u1), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_BOOLEAN;
+       memset (a->data, 0, sizeof(u1) * size);
+
+       return a;
+}
+
+/******************** Funktion: builtin_newarray_char ************************
+
+       Legt ein Array von 16-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_chararray *builtin_newarray_char (s4 size)
+{
+       java_chararray *a;
+       
+       a = heap_allocate ( sizeof(java_chararray) + (size-1) * sizeof(u2), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_CHAR;
+       memset (a->data, 0, sizeof(u2) * size);
+
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_float ***********************
+
+       Legt ein Array von 32-bit-IEEE-float am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_floatarray *builtin_newarray_float (s4 size)
+{
+       s4 i;
+       java_floatarray *a;
+       
+       a = heap_allocate ( sizeof(java_floatarray) + (size-1) * sizeof(float), 
+                           false, NULL );
+       if (!a) return NULL;
+
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_FLOAT;
+       for (i=0; i<size; i++) a->data[i] = 0.0;
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_double ***********************
+
+       Legt ein Array von 64-bit-IEEE-float am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_doublearray *builtin_newarray_double (s4 size)
+{
+       s4 i;
+       java_doublearray *a;
+       
+       a = heap_allocate ( sizeof(java_doublearray) + (size-1) * sizeof(double), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_DOUBLE;
+       for (i=0; i<size; i++) a->data[i] = 0.0;
+       return a;
+}
+
+
+
+
+/******************** Funktion: builtin_newarray_byte ***********************
+
+       Legt ein Array von 8-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_bytearray *builtin_newarray_byte (s4 size)
+{
+       java_bytearray *a;
+       
+       a = heap_allocate ( sizeof(java_bytearray) + (size-1) * sizeof(s1), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array->vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_BYTE;
+       memset (a->data, 0, sizeof(u1) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_short ***********************
+
+       Legt ein Array von 16-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_shortarray *builtin_newarray_short (s4 size)
+{
+       java_shortarray *a;
+       
+       a = heap_allocate ( sizeof(java_shortarray) + (size-1) * sizeof(s2), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_SHORT;
+       memset (a->data, 0, sizeof(s2) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_int ***********************
+
+       Legt ein Array von 32-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_intarray *builtin_newarray_int (s4 size)
+{
+       java_intarray *a;
+       
+       a = heap_allocate ( sizeof(java_intarray) + (size-1) * sizeof(s4), 
+                           false, NULL );
+       if (!a) return NULL;
+       
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_INT;
+       memset (a->data, 0, sizeof(s4) * size);
+       return a;
+}
+
+
+/******************** Funktion: builtin_newarray_long ***********************
+
+       Legt ein Array von 64-bit-Integers am Heap an.
+       Return: Zeiger auf das Array, oder NULL 
+
+*****************************************************************************/
+
+java_longarray *builtin_newarray_long (s4 size)
+{
+       java_longarray *a;
+       
+       a = heap_allocate ( sizeof(java_longarray) + (size-1) * sizeof(s8), 
+                           false, NULL );
+       if (!a) return NULL;
+
+       a -> header.objheader.vftbl = class_array -> vftbl;
+       a -> header.size = size;
+       a -> header.arraytype = ARRAYTYPE_LONG;
+       memset (a->data, 0, sizeof(s8) * size);
+       return a;
+}
+
+
+
+/***************** Funktion: builtin_multianewarray ***************************
+
+       Legt ein mehrdimensionales Array am Heap an.
+       Die Gr"ossen der einzelnen Dimensionen werden in einem Integerarray
+       "ubergeben. Der Typ es zu erzeugenden Arrays wird als 
+       Referenz auf eine constant_arraydescriptor - Struktur "ubergeben.
+
+       Return: Ein Zeiger auf das Array, oder NULL, wenn kein Speicher mehr
+               vorhanden ist.
+
+******************************************************************************/
+
+       /* Hilfsfunktion */
+
+static java_arrayheader *multianewarray_part (java_intarray *dims, int thisdim,
+                       constant_arraydescriptor *desc)
+{
+       u4 size,i;
+       java_arrayarray *a;
+
+       size = dims -> data[thisdim];
+       
+       if (thisdim == (dims->header.size-1)) {
+               /* letzte Dimension schon erreicht */
+               
+               switch (desc -> arraytype) {
+               case ARRAYTYPE_BOOLEAN:  
+                       return (java_arrayheader*) builtin_newarray_boolean (size); 
+               case ARRAYTYPE_CHAR:  
+                       return (java_arrayheader*) builtin_newarray_char (size); 
+               case ARRAYTYPE_FLOAT:  
+                       return (java_arrayheader*) builtin_newarray_float (size); 
+               case ARRAYTYPE_DOUBLE:  
+                       return (java_arrayheader*) builtin_newarray_double (size); 
+               case ARRAYTYPE_BYTE:  
+                       return (java_arrayheader*) builtin_newarray_byte (size); 
+               case ARRAYTYPE_SHORT:  
+                       return (java_arrayheader*) builtin_newarray_short (size); 
+               case ARRAYTYPE_INT:  
+                       return (java_arrayheader*) builtin_newarray_int (size); 
+               case ARRAYTYPE_LONG:  
+                       return (java_arrayheader*) builtin_newarray_long (size); 
+               case ARRAYTYPE_OBJECT:
+                       return (java_arrayheader*) builtin_anewarray (size, desc->objectclass);
+               
+               case ARRAYTYPE_ARRAY:
+                       return (java_arrayheader*) builtin_newarray_array (size, desc->elementdescriptor);
+               
+               default: panic ("Invalid arraytype in multianewarray");
+               }
+               }
+
+       /* wenn letzte Dimension noch nicht erreicht wurde */
+
+       if (desc->arraytype != ARRAYTYPE_ARRAY) 
+               panic ("multianewarray with too many dimensions");
+
+       a = builtin_newarray_array (size, desc->elementdescriptor);
+       if (!a) return NULL;
+       
+       for (i=0; i<size; i++) {
+               java_arrayheader *ea = 
+                 multianewarray_part (dims, thisdim+1, desc->elementdescriptor);
+               if (!ea) return NULL;
+
+               a -> data[i] = ea;
+               }
+               
+       return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+                      constant_arraydescriptor *desc)
+{
+       return multianewarray_part (dims, 0, desc);
+}
+
+
+static java_arrayheader *nmultianewarray_part (int n, long *dims, int thisdim,
+                       constant_arraydescriptor *desc)
+{
+       int size, i;
+       java_arrayarray *a;
+
+       size = (int) dims[thisdim];
+       
+       if (thisdim == (n - 1)) {
+               /* letzte Dimension schon erreicht */
+               
+               switch (desc -> arraytype) {
+               case ARRAYTYPE_BOOLEAN:  
+                       return (java_arrayheader*) builtin_newarray_boolean(size); 
+               case ARRAYTYPE_CHAR:  
+                       return (java_arrayheader*) builtin_newarray_char(size); 
+               case ARRAYTYPE_FLOAT:  
+                       return (java_arrayheader*) builtin_newarray_float(size); 
+               case ARRAYTYPE_DOUBLE:  
+                       return (java_arrayheader*) builtin_newarray_double(size); 
+               case ARRAYTYPE_BYTE:  
+                       return (java_arrayheader*) builtin_newarray_byte(size); 
+               case ARRAYTYPE_SHORT:  
+                       return (java_arrayheader*) builtin_newarray_short(size); 
+               case ARRAYTYPE_INT:  
+                       return (java_arrayheader*) builtin_newarray_int(size); 
+               case ARRAYTYPE_LONG:  
+                       return (java_arrayheader*) builtin_newarray_long(size); 
+               case ARRAYTYPE_OBJECT:
+                       return (java_arrayheader*) builtin_anewarray(size,
+                                                  desc->objectclass);
+               case ARRAYTYPE_ARRAY:
+                       return (java_arrayheader*) builtin_newarray_array(size,
+                                                  desc->elementdescriptor);
+               
+               default: panic ("Invalid arraytype in multianewarray");
+               }
+               }
+
+       /* wenn letzte Dimension noch nicht erreicht wurde */
+
+       if (desc->arraytype != ARRAYTYPE_ARRAY) 
+               panic ("multianewarray with too many dimensions");
+
+       a = builtin_newarray_array(size, desc->elementdescriptor);
+       if (!a) return NULL;
+       
+       for (i = 0; i < size; i++) {
+               java_arrayheader *ea = 
+                       nmultianewarray_part(n, dims, thisdim + 1, desc->elementdescriptor);
+               if (!ea) return NULL;
+
+               a -> data[i] = ea;
+               }
+               
+       return (java_arrayheader*) a;
+}
+
+
+java_arrayheader *builtin_nmultianewarray (int size,
+                      constant_arraydescriptor *desc, long *dims)
+{
+       (void) builtin_newarray_int(size); /* for compatibility with -old */
+       return nmultianewarray_part (size, dims, 0, desc);
+}
+
+
+
+
+/************************* Funktion: builtin_aastore *************************
+
+       speichert eine Referenz auf ein Objekt in einem Object-Array oder
+       in einem Array-Array.
+       Dabei wird allerdings vorher "uberpr"uft, ob diese Operation 
+       zul"assig ist.
+
+       Return: 1, wenn alles OK ist
+               0, wenn dieses Objekt nicht in dieses Array gespeichert werden
+                  darf
+
+*****************************************************************************/
+
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o)
+{
+       if (builtin_canstore(a,o)) {
+               a->data[index] = o;
+               return 1;
+               }
+       return 0;
+}
+
+
+
+
+
+
+/*****************************************************************************
+                      METHODEN-PROTOKOLLIERUNG
+
+       Verschiedene Funktionen, mit denen eine Meldung ausgegeben werden
+       kann, wann immer Methoden aufgerufen oder beendet werden.
+       (f"ur Debug-Zwecke)
+
+*****************************************************************************/
+
+
+u4 methodindent=0;
+
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+                   methodinfo *method, int *pos, int noindent) {
+
+       if (!noindent)
+               methodindent--;
+       if (verbose || runverbose) {
+               printf("Exception ");
+               unicode_display (exceptionptr->vftbl->class->name);
+               printf(" thrown in ");
+               if (method) {
+                       unicode_display (method->class->name);
+                       printf(".");
+                       unicode_display (method->name);
+                       if (method->flags & ACC_SYNCHRONIZED)
+                               printf("(SYNC)");
+                       else
+                               printf("(NOSYNC)");
+                       printf("(%p) at position %p\n", method->entrypoint, pos);
+                       }
+               else
+                       printf("call_java_method\n");
+               fflush (stdout);
+               }
+       return exceptionptr;
+}
+
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5,
+                        methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "called: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       sprintf (logtext+strlen(logtext), "(");
+       switch (method->paramcount) {
+               case 6:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3,  a4,  a5);
+                       break;
+               case 5:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3,  a4);
+                       break;
+               case 4:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
+                                                  a0,  a1,  a2,  a3);
+                       break;
+               case 3:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0,  a1,  a2);
+                       break;
+               case 2:
+                       sprintf(logtext+strlen(logtext), "%lx, %lx", a0,  a1);
+                       break;
+               case 1:
+                       sprintf(logtext+strlen(logtext), "%lx", a0);
+                       break;
+               }
+       sprintf (logtext+strlen(logtext), ")");
+
+       dolog ();
+       methodindent++;
+}
+
+void builtin_displaymethodstart(methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "called: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       dolog ();
+       methodindent++;
+}
+
+void builtin_displaymethodstop(methodinfo *method, long l, double d)
+{
+       methodindent--;
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "finished: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       switch (method->returntype) {
+               case TYPE_INT:
+               case TYPE_LONG:
+                       sprintf (logtext+strlen(logtext), "->%ld", l);
+                       break;
+               case TYPE_FLOAT:
+               case TYPE_DOUBLE:
+                       sprintf (logtext+strlen(logtext), "->%g", d);
+                       break;
+               case TYPE_ADDRESS:
+                       sprintf (logtext+strlen(logtext), "->%p", (void*) l);
+                       break;
+               }
+       dolog ();
+}
+
+void builtin_displaymethodexception(methodinfo *method)
+{
+       sprintf (logtext, "                                             ");
+       sprintf (logtext+methodindent, "exception abort: ");
+       unicode_sprint (logtext+strlen(logtext), method->class->name);
+       sprintf (logtext+strlen(logtext), ".");
+       unicode_sprint (logtext+strlen(logtext), method->name);
+       unicode_sprint (logtext+strlen(logtext), method->descriptor);
+       dolog ();
+}
+
+
+/****************************************************************************
+             SYNCHRONIZATION FUNCTIONS
+*****************************************************************************/
+
+/*
+ * Lock the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_lock_mutex_for_object (java_objectheader *object)
+{
+    mutexHashEntry *entry;
+    int hashValue;
+
+    assert(object != 0);
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object != 0)
+    {
+               if (entry->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       entry->object = 0;
+                       entry->mutex.holder = 0;
+                       entry->mutex.count = 0;
+                       entry->mutex.muxWaiters = 0;
+               }
+       else
+       {
+           while (entry->next != 0 && entry->object != object)
+               entry = entry->next;
+
+           if (entry->object != object)
+           {
+                       entry->next = firstFreeOverflowEntry;
+                       firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+
+                       entry = entry->next;
+                       entry->object = 0;
+                       entry->next = 0;
+                       assert(entry->conditionCount == 0);
+           }
+       }
+    }
+    else
+    {
+               entry->mutex.holder = 0;
+               entry->mutex.count = 0;
+               entry->mutex.muxWaiters = 0;
+    }
+
+    if (entry->object == 0)
+        entry->object = object;
+    
+    internal_lock_mutex(&entry->mutex);
+}
+#endif
+
+
+/*
+ * Unlocks the mutex of an object.
+ */
+#ifdef USE_THREADS
+void
+internal_unlock_mutex_for_object (java_objectheader *object)
+{
+    int hashValue;
+    mutexHashEntry *entry;
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object == object)
+               internal_unlock_mutex(&entry->mutex);
+    else
+    {
+               while (entry->next != 0 && entry->next->object != object)
+                       entry = entry->next;
+
+               assert(entry->next != 0);
+
+               internal_unlock_mutex(&entry->next->mutex);
+
+               if (entry->next->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       mutexHashEntry *unlinked = entry->next;
+
+                       entry->next = unlinked->next;
+                       unlinked->next = firstFreeOverflowEntry;
+                       firstFreeOverflowEntry = unlinked;
+               }
+    }
+}
+#endif
+
+void
+builtin_monitorenter (java_objectheader *o)
+{
+#ifdef USE_THREADS
+    int hashValue;
+
+       assert(blockInts == 0);
+
+    ++blockInts;
+
+    hashValue = MUTEX_HASH_VALUE(o);
+    if (mutexHashTable[hashValue].object == o
+               && mutexHashTable[hashValue].mutex.holder == currentThread)
+               ++mutexHashTable[hashValue].mutex.count;
+    else
+               internal_lock_mutex_for_object(o);
+
+       --blockInts;
+
+       assert(blockInts == 0);
+#endif
+}
+
+void builtin_monitorexit (java_objectheader *o)
+{
+#ifdef USE_THREADS
+    int hashValue;
+
+       assert(blockInts == 0);
+
+    ++blockInts;
+
+    hashValue = MUTEX_HASH_VALUE(o);
+    if (mutexHashTable[hashValue].object == o)
+    {
+               if (mutexHashTable[hashValue].mutex.count == 1
+                       && mutexHashTable[hashValue].mutex.muxWaiters != 0)
+                       internal_unlock_mutex_for_object(o);
+               else
+                       --mutexHashTable[hashValue].mutex.count;
+    }
+    else
+               internal_unlock_mutex_for_object(o);
+
+       --blockInts;
+
+       assert(blockInts == 0);
+#endif
+}
+
+
+/*****************************************************************************
+                      DIVERSE HILFSFUNKTIONEN
+*****************************************************************************/
+
+
+
+/*********** Funktionen f"ur die Integerdivision *****************************
+       Auf manchen Systemen (z.B. DEC ALPHA) wird durch die CPU keine Integer-
+       division unterst"utzt.
+       Daf"ur gibt es dann diese Hilfsfunktionen
+
+******************************************************************************/
+
+s4 builtin_idiv (s4 a, s4 b) { return a/b; }
+s4 builtin_irem (s4 a, s4 b) { return a%b; }
+
+
+/************** Funktionen f"ur Long-Arithmetik *******************************
+
+       Auf Systemen, auf denen die CPU keine 64-Bit-Integers unterst"utzt,
+       werden diese Funktionen gebraucht
+
+******************************************************************************/
+
+
+s8 builtin_ladd (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a+b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lsub (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a-b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lmul (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a*b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_ldiv (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a/b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lrem (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a%b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshl (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return a<<(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lshr (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return a>>(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lushr (s8 a, s4 b) 
+{ 
+#if U8_AVAILABLE
+       return ((u8)a)>>(b&63);
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_land (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a&b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lor (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a|b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lxor (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       return a^b; 
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s8 builtin_lneg (s8 a) 
+{ 
+#if U8_AVAILABLE
+       return -a;
+#else
+       return builtin_i2l(0);
+#endif
+}
+
+s4 builtin_lcmp (s8 a, s8 b) 
+{ 
+#if U8_AVAILABLE
+       if (a<b) return -1;
+       if (a>b) return 1;
+       return 0;
+#else
+       return 0;
+#endif
+}
+
+
+
+
+
+/*********** Funktionen f"ur die Floating-Point-Operationen ******************/
+
+float builtin_fadd (float a, float b)
+{
+       if (isnanf(a)) return FLT_NAN;
+       if (isnanf(b)) return FLT_NAN;
+       if (finitef(a)) {
+               if (finitef(b)) return a+b;
+               else return b;
+               }
+       else {
+               if (finitef(b)) return a;
+               else {
+                       if (copysignf(1.0, a)==copysignf(1.0, b)) return a;
+                       else  return FLT_NAN;
+                       }
+               }
+}
+
+float builtin_fsub (float a, float b)
+{
+       return builtin_fadd (a, builtin_fneg(b));
+}
+
+float builtin_fmul (float a, float b)
+{
+       if (isnanf(a)) return FLT_NAN;
+       if (isnanf(b)) return FLT_NAN;
+       if (finitef(a)) {
+               if (finitef(b)) return a*b;
+               else {
+                       if (a==0) return FLT_NAN;
+                            else return copysignf(b, copysignf(1.0, b)*a);
+                       }
+               }
+       else {
+               if (finitef(b)) {
+                       if (b==0) return FLT_NAN;
+                            else return copysignf(a, copysignf(1.0, a)*b);
+                       }
+               else {
+                       return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+                       }
+               }
+}
+
+float builtin_fdiv (float a, float b)
+{
+       if (finitef(a) && finitef(b)) {
+               if (b != 0)
+                       return a / b;
+               else {
+                       if (a > 0)
+                               return FLT_POSINF;
+                       else if (a < 0)
+                               return FLT_NEGINF;
+                       }
+               }
+       return FLT_NAN;
+}
+
+float builtin_frem (float a, float b)
+{
+
+/* return (float) builtin_drem((double) a, (double) b); */
+
+       float f;
+
+       if (finite((double) a) && finite((double) b)) {
+               f = a / b;
+               if (finite((double) f))
+                       return fmodf(a, b);
+               return FLT_NAN;
+               }
+       if (isnan((double) b))
+               return FLT_NAN;
+       if (finite((double) a))
+               return a;
+       return FLT_NAN;
+
+/*     float f;
+
+       if (finitef(a) && finitef(b)) {
+               f = a / b;
+               if (finitef(f))
+                       return a - floorf(f) * b;
+               return FLT_NAN;
+               }
+       if (isnanf(b))
+               return FLT_NAN;
+       if (finitef(a))
+               return a;
+       return FLT_NAN; */
+}
+
+
+float builtin_fneg (float a)
+{
+       if (isnanf(a)) return a;
+       else {
+               if (finitef(a)) return -a;
+                          else return copysignf(a,-copysignf(1.0, a));
+               }
+}
+
+s4 builtin_fcmpl (float a, float b)
+{
+       if (isnanf(a)) return -1;
+       if (isnanf(b)) return -1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0,  a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+s4 builtin_fcmpg (float a, float b)
+{
+       if (isnanf(a)) return 1;
+       if (isnanf(b)) return 1;
+       if (!finitef(a) || !finitef(b)) {
+               a = finitef(a) ? 0 : copysignf(1.0, a);
+               b = finitef(b) ? 0 : copysignf(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+
+
+/*********** Funktionen f"ur doppelt genaue Fliesskommazahlen ***************/
+
+double builtin_dadd (double a, double b)
+{
+       if (isnan(a)) return DBL_NAN;
+       if (isnan(b)) return DBL_NAN;
+       if (finite(a)) {
+               if (finite(b)) return a+b;
+               else return b;
+               }
+       else {
+               if (finite(b)) return a;
+               else {
+                       if (copysign(1.0, a)==copysign(1.0, b)) return a;
+                       else  return DBL_NAN;
+                       }
+               }
+}
+
+double builtin_dsub (double a, double b)
+{
+       return builtin_dadd (a, builtin_dneg(b));
+}
+
+double builtin_dmul (double a, double b)
+{
+       if (isnan(a)) return DBL_NAN;
+       if (isnan(b)) return DBL_NAN;
+       if (finite(a)) {
+               if (finite(b)) return a*b;
+               else {
+                       if (a==0) return DBL_NAN;
+                            else return copysign(b, copysign(1.0, b)*a);
+                       }
+               }
+       else {
+               if (finite(b)) {
+                       if (b==0) return DBL_NAN;
+                            else return copysign(a, copysign(1.0, a)*b);
+                       }
+               else {
+                       return copysign(a, copysign(1.0, a)*copysign(1.0, b));
+                       }
+               }
+}
+
+double builtin_ddiv (double a, double b)
+{
+       if (finite(a) && finite(b)) {
+               if (b != 0)
+                       return a / b;
+               else {
+                       if (a > 0)
+                               return DBL_POSINF;
+                       else if (a < 0)
+                               return DBL_NEGINF;
+                       }
+               }
+       return DBL_NAN;
+}
+
+double builtin_drem (double a, double b)
+{
+       double d;
+
+       if (finite(a) && finite(b)) {
+               d = a / b;
+               if (finite(d)) {
+                       if ((d < 1.0) && (d > 0.0))
+                               return a;
+                       return fmod(a, b);
+                       }
+               return DBL_NAN;
+               }
+       if (isnan(b))
+               return DBL_NAN;
+       if (finite(a))
+               return a;
+       return DBL_NAN;
+}
+
+double builtin_dneg (double a)
+{
+       if (isnan(a)) return a;
+       else {
+               if (finite(a)) return -a;
+                         else return copysign(a,-copysign(1.0, a));
+               }
+}
+
+s4 builtin_dcmpl (double a, double b)
+{
+       if (isnan(a)) return -1;
+       if (isnan(b)) return -1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+s4 builtin_dcmpg (double a, double b)
+{
+       if (isnan(a)) return 1;
+       if (isnan(b)) return 1;
+       if (!finite(a) || !finite(b)) {
+               a = finite(a) ? 0 : copysign(1.0, a);
+               b = finite(b) ? 0 : copysign(1.0, b);
+               }
+       if (a>b) return 1;
+       if (a==b) return 0;
+       return -1;
+}
+
+
+/*********************** Umwandlungsoperationen ****************************/
+
+s8 builtin_i2l (s4 i)
+{
+#if U8_AVAILABLE
+       return i;
+#else
+       s8 v; v.high = 0; v.low=i; return v;
+#endif
+}
+
+float builtin_i2f (s4 a)
+{
+float f = (float) a;
+return f;
+}
+
+double builtin_i2d (s4 a)
+{
+double d = (double) a;
+return d;
+}
+
+
+s4 builtin_l2i (s8 l)
+{
+#if U8_AVAILABLE
+       return (s4) l;
+#else
+       return l.low;
+#endif
+}
+
+float builtin_l2f (s8 a)
+{
+#if U8_AVAILABLE
+       float f = (float) a;
+       return f;
+#else
+       return 0.0;
+#endif
+}
+
+double builtin_l2d (s8 a)
+{
+#if U8_AVAILABLE
+       double d = (double) a;
+       return d;
+#else
+       return 0.0;
+#endif
+}
+
+
+s4 builtin_f2i(float a) 
+{
+
+return builtin_d2i((double) a);
+
+/*     float f;
+       
+       if (isnanf(a))
+               return 0;
+       if (finitef(a)) {
+               if (a > 2147483647)
+                       return 2147483647;
+               if (a < (-2147483648))
+                       return (-2147483648);
+               return (s4) a;
+               }
+       f = copysignf((float) 1.0, a);
+       if (f > 0)
+               return 2147483647;
+       return (-2147483648); */
+}
+
+
+s8 builtin_f2l (float a)
+{
+
+return builtin_d2l((double) a);
+
+/*     float f;
+       
+       if (finitef(a)) {
+               if (a > 9223372036854775807L)
+                       return 9223372036854775807L;
+               if (a < (-9223372036854775808L))
+                       return (-9223372036854775808L);
+               return (s8) a;
+               }
+       if (isnanf(a))
+               return 0;
+       f = copysignf((float) 1.0, a);
+       if (f > 0)
+               return 9223372036854775807L;
+       return (-9223372036854775808L); */
+}
+
+
+double builtin_f2d (float a)
+{
+       if (finitef(a)) return (double) a;
+       else {
+               if (isnanf(a)) return DBL_NAN;
+               else           return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+               }
+}
+
+
+s4 builtin_d2i (double a) 
+{ 
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 2147483647)
+                       return 2147483647;
+               if (a <= (-2147483648))
+                       return (-2147483648);
+               return (s4) a;
+               }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 2147483647;
+       return (-2147483648);
+}
+
+
+s8 builtin_d2l (double a)
+{
+       double d;
+       
+       if (finite(a)) {
+               if (a >= 9223372036854775807L)
+                       return 9223372036854775807L;
+               if (a <= (-9223372036854775807L-1))
+                       return (-9223372036854775807L-1);
+               return (s8) a;
+               }
+       if (isnan(a))
+               return 0;
+       d = copysign(1.0, a);
+       if (d > 0)
+               return 9223372036854775807L;
+       return (-9223372036854775807L-1);
+}
+
+
+float builtin_d2f (double a)
+{
+       if (finite(a)) return (float) a;
+       else {
+               if (isnan(a)) return FLT_NAN;
+               else          return copysignf (FLT_POSINF, (float) copysign(1.0, a));
+               }
+}
+
diff --git a/src/vm/builtin.h b/src/vm/builtin.h
new file mode 100644 (file)
index 0000000..b52afb4
--- /dev/null
@@ -0,0 +1,125 @@
+/****************************** builtin.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the prototypes for the functions of file builtin.c which has
+       a more detailed description.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/14
+
+*******************************************************************************/
+
+
+/***************************** Prototypes *************************************/       
+
+typedef struct builtin_descriptor {
+       functionptr bptr;
+       char        *name;
+       } builtin_descriptor;
+
+extern builtin_descriptor builtin_desc[];
+
+s4 builtin_instanceof(java_objectheader *obj, classinfo *class);
+s4 builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 new_builtin_checkcast(java_objectheader *obj, classinfo *class);
+s4 builtin_arrayinstanceof
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 builtin_checkarraycast
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+s4 new_builtin_checkarraycast
+       (java_objectheader *obj, constant_arraydescriptor *desc);
+
+java_objectheader *builtin_throw_exception (java_objectheader *exception);
+java_objectheader *builtin_trace_exception (java_objectheader *exceptionptr,
+                   methodinfo *method, int *pos, int noindent);
+
+java_objectheader *builtin_new (classinfo *c);
+
+
+java_objectarray *builtin_anewarray (s4 size, classinfo *elementtype);
+java_arrayarray *builtin_newarray_array 
+        (s4 size, constant_arraydescriptor *elementdesc);
+java_booleanarray *builtin_newarray_boolean (s4 size);
+java_chararray *builtin_newarray_char (s4 size);
+java_floatarray *builtin_newarray_float (s4 size);
+java_doublearray *builtin_newarray_double (s4 size);
+java_bytearray *builtin_newarray_byte (s4 size);
+java_shortarray *builtin_newarray_short (s4 size);
+java_intarray *builtin_newarray_int (s4 size);
+java_longarray *builtin_newarray_long (s4 size);
+java_arrayheader *builtin_multianewarray (java_intarray *dims,
+                       constant_arraydescriptor *desc);
+java_arrayheader *builtin_nmultianewarray (int size,
+                      constant_arraydescriptor *desc, long *dims);
+
+s4 builtin_canstore (java_objectarray *a, java_objectheader *o);
+s4 builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+void new_builtin_aastore (java_objectarray *a, s4 index, java_objectheader *o);
+
+void builtin_trace_args(long a0, long a1, long a2, long a3, long a4, long a5, methodinfo *method);
+void builtin_displaymethodstart(methodinfo *method);
+void builtin_displaymethodstop(methodinfo *method, long l, double d);
+/* void builtin_displaymethodstop(methodinfo *method); */
+void builtin_displaymethodexception(methodinfo *method);
+
+void builtin_monitorenter (java_objectheader *o);
+void new_builtin_monitorenter (java_objectheader *o);
+void builtin_monitorexit (java_objectheader *o);
+void new_builtin_monitorexit (java_objectheader *o);
+
+s4 builtin_idiv (s4 a, s4 b); 
+s4 new_builtin_idiv (s4 a, s4 b); 
+s4 builtin_irem (s4 a, s4 b);
+s4 new_builtin_irem (s4 a, s4 b);
+
+s8 builtin_ladd (s8 a, s8 b);
+s8 builtin_lsub (s8 a, s8 b);
+s8 builtin_lmul (s8 a, s8 b);
+s8 builtin_ldiv (s8 a, s8 b);
+s8 new_builtin_ldiv (s8 a, s8 b);
+s8 builtin_lrem (s8 a, s8 b);
+s8 new_builtin_lrem (s8 a, s8 b);
+s8 builtin_lshl (s8 a, s4 b);
+s8 builtin_lshr (s8 a, s4 b);
+s8 builtin_lushr (s8 a, s4 b);
+s8 builtin_land (s8 a, s8 b);
+s8 builtin_lor (s8 a, s8 b);
+s8 builtin_lxor (s8 a, s8 b);
+s8 builtin_lneg (s8 a);
+s4 builtin_lcmp (s8 a, s8 b);
+
+float builtin_fadd (float a, float b);
+float builtin_fsub (float a, float b);
+float builtin_fmul (float a, float b);
+float builtin_fdiv (float a, float b);
+float builtin_frem (float a, float b);
+float builtin_fneg (float a);
+s4 builtin_fcmpl (float a, float b);
+s4 builtin_fcmpg (float a, float b);
+
+double builtin_dadd (double a, double b);
+double builtin_dsub (double a, double b);
+double builtin_dmul (double a, double b);
+double builtin_ddiv (double a, double b);
+double builtin_drem (double a, double b);
+double builtin_dneg (double a);
+s4 builtin_dcmpl (double a, double b);
+s4 builtin_dcmpg (double a, double b);
+
+s8       builtin_i2l (s4 i);
+float    builtin_i2f (s4 i);
+double   builtin_i2d (s4 i);
+s4       builtin_l2i (s8 l);
+float    builtin_l2f (s8 l);
+double   builtin_l2d (s8 l);
+s4       builtin_f2i (float a);
+s8       builtin_f2l (float a);
+double   builtin_f2d (float a);
+s4       builtin_d2i (double a);
+s8       builtin_d2l (double a);
+float    builtin_d2f (double a);
+
diff --git a/src/vm/global.h b/src/vm/global.h
new file mode 100644 (file)
index 0000000..e92f7f1
--- /dev/null
@@ -0,0 +1,542 @@
+/****************************** global.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains global definitions which are used in the whole program, includes
+       some files and contains global used macros.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Chages:  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/28
+
+*******************************************************************************/
+
+#ifndef __global_h_
+#define __global_h_                        /* schani */
+
+#define STATISTICS                         /* andi   */
+
+/***************************** standard includes ******************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "toolbox/memory.h"
+#include "toolbox/chain.h"
+#include "toolbox/list.h"
+#include "toolbox/loging.h"
+
+
+/**************************** system dependent types **************************/
+
+#include "sysdep/types.h"
+
+
+/**************************** additional data types ***************************/
+
+typedef void *voidptr;          /* generic pointer */
+
+
+typedef u1    bool;             /* boolean data type */
+
+#define true  1
+#define false 0
+
+typedef void (*functionptr) (); /* generic function pointer */
+
+
+#define MAX_ALIGN 8             /* most generic alignment for JavaVM values   */
+
+
+/**************************** shutdown function *******************************/
+
+void cacao_shutdown(s4 status);
+
+
+/**************************** basic data types ********************************/
+
+#define TYPE_INT      0         /* the JavaVM types must numbered in the      */
+#define TYPE_LONG     1         /* same order as the ICMD_Ixxx to ICMD_Axxx   */
+#define TYPE_FLOAT    2         /* instructions (LOAD and STORE)              */
+#define TYPE_DOUBLE   3         /* integer, long, float, double, address      */
+#define TYPE_ADDRESS  4         /* all other types can be numbered arbitrarily*/
+
+#define TYPE_VOID    10
+
+
+/**************************** Java class file constants ***********************/
+
+#define MAGIC         0xcafebabe
+#define MINOR_VERSION 3
+#define MAJOR_VERSION 45
+
+#define CONSTANT_Class                7
+#define CONSTANT_Fieldref             9
+#define CONSTANT_Methodref           10
+#define CONSTANT_InterfaceMethodref  11
+#define CONSTANT_String               8
+#define CONSTANT_Integer              3
+#define CONSTANT_Float                4
+#define CONSTANT_Long                 5
+#define CONSTANT_Double               6
+#define CONSTANT_NameAndType         12
+#define CONSTANT_Utf8                 1
+
+#define CONSTANT_Arraydescriptor     13
+#define CONSTANT_UNUSED               0
+
+
+#define ACC_PUBLIC                0x0001
+#define ACC_PRIVATE               0x0002
+#define ACC_PROTECTED             0x0004
+#define ACC_STATIC                0x0008
+#define ACC_FINAL                 0x0010
+#define ACC_SYNCHRONIZED          0x0020
+#define ACC_VOLATILE              0x0040
+#define ACC_TRANSIENT             0x0080
+#define ACC_NATIVE                0x0100
+#define ACC_INTERFACE             0x0200
+#define ACC_ABSTRACT              0x0400
+
+
+
+/**************************** resolve typedef-cycles **************************/
+
+typedef struct unicode unicode;
+typedef struct classinfo classinfo; 
+typedef struct vftbl vftbl;
+typedef u1* methodptr;
+
+
+/********************** data structures of UNICODE symbol *********************/
+
+struct unicode {
+       unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+       u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+       int        length;   /* L"ange des Textes */           
+       u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+       classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
+                               Namens (oder NULL, wenn es keine solche gibt)  */
+       struct java_objectheader *string;
+                            /* gegebenenfalls Referenz auf einen konstanten
+                               String mit dem entsprechenden Wert */ 
+       };
+
+       /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
+          (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
+          -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
+          Zeigervergleich */
+
+
+/************ data structures of remaining constant pool entries **************/
+
+
+typedef struct {
+       classinfo *class;
+       unicode   *name;
+       unicode   *descriptor;
+       } constant_FMIref;
+
+
+typedef struct {
+       s4 value;
+       } constant_integer;
+       
+typedef struct {
+       float value;
+       } constant_float;
+
+typedef struct {
+       s8 value;
+       } constant_long;
+       
+typedef struct {
+       double value;
+       } constant_double;
+
+
+typedef struct {
+       unicode *name;
+       unicode *descriptor;
+       } constant_nameandtype;
+
+
+typedef struct constant_arraydescriptor {
+       int arraytype;
+       classinfo *objectclass;
+       struct constant_arraydescriptor *elementdescriptor;
+       } constant_arraydescriptor;
+
+       /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+          Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
+       dass das Feld arraytype die entsprechende Kennzahl enth"alt
+       (z.B. ARRAYTYPE_BYTE).
+       Bei Arrays von Objekten (arraytype=ARRAYTYPE_OBJECT) muss das 
+       Feld objectclass auf die Klassenstruktur der m"oglichen
+       Element-Objekte zeigen.
+       Bei Arrays von Arrays (arraytype=ARRAYTYPE_ARRAY) muss das
+       Feld elementdescriptor auf eine weiter arraydescriptor-Struktur
+       zeigen, die die Element-Typen beschreibt.
+       */
+
+
+
+/********* Anmerkungen zum Constant-Pool:
+
+       Die Typen der Eintr"age in den Constant-Pool werden durch die oben
+       definierten CONSTANT_.. Werte angegeben.
+       Bei allen Typen muss zus"atzlich noch eine Datenstruktur hinzugef"ugt
+       werden, die den wirklichen Wert angibt.
+       Bei manchen Typen reicht es, einen Verweis auf eine schon bereits
+       existierende Struktur (z.B. unicode-Texte) einzutragen, bei anderen
+       muss diese Struktur erst extra erzeugt werden.
+       Ich habe folgende Datenstrukturen f"ur diese Typen verwendet:
+       
+               Typ                      Struktur                    extra erzeugt?
+       ----------------------------------------------------------------------
+    CONSTANT_Class               classinfo                         nein
+    CONSTANT_Fieldref            constant_FMIref                     ja
+    CONSTANT_Methodref           constant_FMIref                     ja
+    CONSTANT_InterfaceMethodref  constant_FMIref                     ja
+    CONSTANT_String              unicode                           nein
+    CONSTANT_Integer             constant_integer                    ja
+    CONSTANT_Float               constant_float                      ja
+    CONSTANT_Long                constant_long                       ja
+    CONSTANT_Double              constant_double                     ja
+    CONSTANT_NameAndType         constant_nameandtype                ja
+    CONSTANT_Utf8                unicode                           nein
+    CONSTANT_Arraydescriptor     constant_arraydescriptor            ja
+    CONSTANT_UNUSED              -
+
+*******************************/
+
+
+
+/***************** Die Datenstrukturen fuer das Laufzeitsystem ***************/
+
+
+       /********* Objekte **********
+
+       Alle Objekte (und Arrays), die am Heap gespeichert werden, m"ussen eine 
+       folgende spezielle Datenstruktur ganz vorne stehen haben: 
+
+       */
+
+typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
+       vftbl *vftbl;                     /* Zeiger auf die Function Table */
+} java_objectheader;
+
+
+
+       /********* Arrays ***********
+       
+       Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
+       den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
+       Es gibt aber (der Einfachheit halber) nur eine einzige Klasse f"ur alle
+       m"oglichen Typen von Arrays, deshalb wird der tats"achliche Typ in einem
+       Feld im Array-Objekt selbst gespeichert.
+       Die Typen sind: */
+
+#define ARRAYTYPE_INT      0
+#define ARRAYTYPE_LONG     1
+#define ARRAYTYPE_FLOAT    2
+#define ARRAYTYPE_DOUBLE   3
+#define ARRAYTYPE_BYTE     4
+#define ARRAYTYPE_CHAR     5
+#define ARRAYTYPE_SHORT    6
+#define ARRAYTYPE_BOOLEAN  7
+#define ARRAYTYPE_OBJECT   8
+#define ARRAYTYPE_ARRAY    9
+
+
+       /** Der Header f"ur ein Java-Array **/
+
+typedef struct java_arrayheader {  /* Der Arrayheader f"ur alle Arrays */
+       java_objectheader objheader;       /* Der Object-Header */
+       s4 size;                           /* Gr"osse des Arrays */
+       s4 arraytype;                      /* Typ der Elemente */
+} java_arrayheader;
+
+
+
+       /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+
+typedef struct java_chararray {
+       java_arrayheader header;
+       u2 data[1];
+} java_chararray;
+
+typedef struct java_floatheader {
+       java_arrayheader header;
+       float data[1];
+} java_floatarray;
+
+typedef struct java_doublearray {
+       java_arrayheader header;
+       double data[1];
+} java_doublearray;
+
+
+   /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
+      identisches memory-layout haben, weil mit den selben Funktionen 
+      darauf zugegriffen wird */
+
+typedef struct java_booleanarray {
+       java_arrayheader header;
+       u1 data[1];
+} java_booleanarray;
+
+typedef struct java_bytearray {
+       java_arrayheader header;
+       s1 data[1];
+} java_bytearray;
+
+typedef struct java_shortarray {
+       java_arrayheader header;
+       s2 data[1];
+} java_shortarray;
+
+typedef struct java_intarray {
+       java_arrayheader header;
+       s4 data[1];
+} java_intarray;
+
+typedef struct java_longarray {
+       java_arrayheader header;
+       s8 data[1];
+} java_longarray;
+
+
+       /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+          Memory-Layout haben, weil mit ein und der selben Funktion auf die
+          data-Eintr"age beider Typen zugegriffen wird !!!! */
+
+typedef struct java_objectarray {
+       java_arrayheader header;
+       classinfo *elementtype;
+       java_objectheader *data[1];
+} java_objectarray;
+
+typedef struct java_arrayarray {
+       java_arrayheader header;
+       constant_arraydescriptor *elementdescriptor;
+       java_arrayheader *data[1];
+} java_arrayarray;
+
+
+
+
+/************** Strukturen f"ur Klassen, Felder & Methoden *****************/
+
+
+    /*** Struktur: fieldinfo ***/
+
+typedef struct fieldinfo {   /* Struktur f"ur ein Feld einer Klasse */
+       s4       flags;              /* die ACC-Flags */
+       s4       type;               /* Grunddatentyp */
+       unicode *name;               /* Name des Felds */
+       unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
+       
+       s4       offset;             /* Offset vom Anfang des Objektes */
+                                    /* (bei Instanzvariablen) */
+
+       union {                      /* Speicher f"ur den Wert */
+               s4 i;                    /* (bei Klassenvariablen) */    
+               s8 l;
+               float f;
+               double d;
+               void *a; 
+               } value;
+               
+       } fieldinfo;
+
+
+    /*** Struktur: exceptiontable ***/
+
+typedef struct exceptiontable {  /* Exceptionhandler-Eintrag in einer Methode */ 
+       s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
+       s4         endpc;              /* Ende des Bereichs (exklusive) */
+       s4         handlerpc;          /* JavaVM-Position des Handlers */
+       classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
+                                       NULL, wenn alle behandelt werden sollen) */
+       } exceptiontable;
+
+
+
+    /*** Struktur: methodinfo ***/
+
+typedef struct methodinfo {  /* Struktur f"ur eine Methode einer Klasse */
+       s4             flags;            /* die ACC-Flags */
+       unicode   *name;             /* Name der Methode */
+       unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
+       s4        returntype;        /* only temporary valid, return type */
+       s4        paramcount;        /* only temporary valid, number of parameters */
+       u1        *paramtypes;       /* only temporary valid, parameter types */
+       classinfo *class;            /* Die Klasse, der die Methode geh"ort */
+       u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
+                                       Function Table (wenn es keine statische
+                                       Methode ist) */
+
+       s4       maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
+       s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
+       u4   jcodelength;               /* L"ange des JavaVM-Codes */
+       u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
+
+       s4   exceptiontablelength;      /* L"ange der Exceptintable */
+       exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+       u1  *stubroutine;               /* STUB-Routine for compiling or calling 
+                                          natives */   
+       u4   mcodelength;               /* L"ange des generierten Maschinencodes */
+       u1  *mcode;                     /* Zeiger auf den Maschinencode */
+       u1  *entrypoint;                /* Entrypoint to the Maschine-Code */
+
+       
+       } methodinfo;
+
+
+    /*** Struktur: classinfo ***/
+
+struct classinfo {           /* Datenstruktur f"ur eine Klasse */
+       java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
+                                        werden */
+
+       s4 flags;                     /* Die ACC-Flags */
+       unicode *name;                /* Name der Klasse */ 
+       
+       s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
+       u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
+       voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
+       
+       classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
+       
+       s4          interfacescount;  /* Anzahl der Interfaces */
+       classinfo **interfaces;       /* Zeiger auf die Interfaces */
+       
+       s4          fieldscount;      /* Anzahl der Felder */
+       fieldinfo  *fields;           /* Die Tabelle der Felder */
+       
+       s4          methodscount;     /* Anzahl der Methoden */
+       methodinfo *methods;          /* Die Tabelle der Methoden */
+       
+       
+       listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
+
+       bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
+       bool        linked;           /* wird von `class_link` auf true gesetzt */
+       s4                      index;            /* Hierarchietiefe  (bei normalen Klassen)  
+                                        oder fortlaufende Nummer (bei Interfaces)*/ 
+       u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
+
+       vftbl       *vftbl;
+
+       methodinfo *finalizer;        /* Finalizer-Methode f"ur die Klasse */
+       };
+       
+
+struct vftbl {
+       classinfo  *class;            /* Class, the function table belongs to */
+
+       s4          vftbllength;      /* L"aenge der Virtual Function Table */
+
+       s4          interfacetablelength;   /* L"ange der Interfacetable */   
+       u4         *interfacevftbllength;   /* -> siehe unten */   
+       methodptr **interfacevftbl;
+       
+       methodptr   table[1];
+       };
+
+/*********** Anmerkungen zur Interfacetable: 
+
+       "Ahnlich wie die 'normalen' virtuellen Methoden k"onnen auch die
+       Interface-Methoden mit Hilfe einer Art Virtual Function Table 
+       aufgerufen werden.
+       Dazu werden alle Interfaces im System fortlaufend nummeriert (beginnend
+       bei 0), und f"ur jede Klasse wird eine ganze Tabelle von 
+       Virtual Function Tables erzeugt, n"amlich zu jedem Interface, das die
+       Klasse implementiert, eine.
+
+       z.B. Nehmen wir an, eine Klasse implementiert zwei Interfaces (die durch
+       die Nummerierung die Indizes 0 und 3 bekommen haben)
+
+       Das sieht dann ungef"ahr so aus:
+                               --------------           ------------- 
+       interfacevftbl ---> | Eintrag 0  |---------> | Methode 0 |---> Methode X 
+                        | Eintrag 1  |--> NULL   | Methode 1 |---> Methode Y
+                        | Eintrag 2  |--> NULL   | Methode 2 |---> Methode Z
+                        | Eintrag 3  |-----+     ------------- 
+                        --------------     |
+                                           +---> -------------
+                                                 | Methode 0 |---> Methode X
+                                                 | Methode 1 |---> Methode A
+                                                 -------------
+                              ---------------
+       interfacevftlblength ---> | Wert 0 = 3  |
+                                 | Wert 1 = 0  |
+                                 | Wert 2 = 0  |
+                                 | Wert 3 = 2  |
+                                 ---------------
+
+       Der Aufruf einer Interface-Methode geht dann so vor sich:
+       Zur Compilezeit steht der Index (i) des Interfaces und die Stelle (s), wo
+       in der entsprechenden Untertabelle die Methode eingetragen ist, schon fest.
+       Also muss zur Laufzeit nur mehr der n-te Eintrag aus der Interfacetable 
+       gelesen werden, von dieser Tabelle aus wird der s-te Eintrag geholt,
+       und diese Methode wird angesprungen.
+
+****************/
+
+
+
+/************************* Referenzen auf die wichtigen Systemklassen ********************/
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_ClassCastException;
+extern classinfo *class_java_lang_NullPointerException;
+extern classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+extern classinfo *class_java_lang_NegativeArraySizeException;
+extern classinfo *class_java_lang_OutOfMemoryError;
+extern classinfo *class_java_lang_ArithmeticException;
+extern classinfo *class_java_lang_ArrayStoreException;
+extern classinfo *class_java_lang_ThreadDeath;              /* schani */
+extern classinfo *class_array;
+
+
+/********************** Vorgefertigte Instanzen einiger Systemklassen ********************/
+
+extern java_objectheader *proto_java_lang_ClassCastException;
+extern java_objectheader *proto_java_lang_NullPointerException;
+extern java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+extern java_objectheader *proto_java_lang_NegativeArraySizeException;
+extern java_objectheader *proto_java_lang_OutOfMemoryError;
+extern java_objectheader *proto_java_lang_ArithmeticException;
+extern java_objectheader *proto_java_lang_ArrayStoreException;
+extern java_objectheader *proto_java_lang_ThreadDeath;      /* schani */
+
+
+/********************** flag variables *********************/
+
+extern bool compileall;
+extern bool runverbose;         
+extern bool verbose;         
+                                
+
+/********************** trace variables ********************/
+
+extern int count_class_infos;
+extern int count_const_pool_len;
+extern int count_vftbl_len;
+extern int count_unicode_len;
+extern int count_all_methods;
+extern int count_vmcode_len;
+extern int count_extable_len;
+
+#endif
diff --git a/src/vm/jit/asmpart.h b/src/vm/jit/asmpart.h
new file mode 100644 (file)
index 0000000..927ccd1
--- /dev/null
@@ -0,0 +1,41 @@
+/****************************** asmpart.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Headerfile for asmpart.S. asmpart.S contains the machine dependent
+       Java - C interface functions.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/10/15
+
+*******************************************************************************/
+
+int has_no_x_instr_set();
+       /* determines if the byte support instruction set (21164a and higher)
+          is available. */
+
+void synchronize_caches();
+
+
+void asm_call_jit_compiler ();
+       /* invokes the compiler for untranslated JavaVM methods.
+          Register R0 contains a pointer to the method info structure
+          (prepared by createcompilerstub). */
+
+java_objectheader *asm_calljavamethod (methodinfo *m, void *arg1, void*arg2,
+                                       void*arg3, void*arg4);
+       /* This function calls a Java-method (which possibly needs compilation)
+          with up to 4 parameters. This function calls a Java-method (which
+          possibly needs compilation) with up to 4 parameters. */
+
+
+void asm_dumpregistersandcall ( functionptr f);
+       /* This funtion saves all callee saved registers and calls the function
+          which is passed as parameter.
+          This function is needed by the garbage collector, which needs to access
+          all registers which are stored on the stack. Unused registers are
+          cleared to avoid interferances with the GC. */
diff --git a/src/vm/loader.c b/src/vm/loader.c
new file mode 100644 (file)
index 0000000..c94327c
--- /dev/null
@@ -0,0 +1,1994 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** loader.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the functions of the class loader.
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/06/03
+
+*******************************************************************************/
+
+
+#include <assert.h>
+
+#include "global.h"
+#include "loader.h"
+
+#include "tables.h"
+#include "native.h"
+#include "builtin.h"
+#include "compiler.h"
+#include "asmpart.h"
+
+#include "threads/thread.h"                        /* schani */
+
+
+/*************************** globale Variablen *******************************/
+
+extern bool newcompiler;               
+
+int count_class_infos = 0;
+int count_const_pool_len = 0;
+int count_vftbl_len = 0;
+int count_all_methods = 0;
+int count_vmcode_len = 0;
+int count_extable_len = 0;
+
+bool loadverbose = false;        /* Switches f"ur mehr Debug-Meldungen */
+bool linkverbose = false;
+bool initverbose = false;
+
+bool makeinitializations = true;
+
+bool getloadingtime = false;
+long int loadingtime = 0;
+
+
+static u4 interfaceindex;        /* fortlaufende Nummer f"ur Interfaces */ 
+
+static list unloadedclasses;     /* Liste alle referenzierten, aber noch nicht 
+                                    geladenen Klassen */
+static list unlinkedclasses;     /* Liste aller geladenen, aber noch nicht
+                                    gelinkten Klassen */ 
+       list linkedclasses;       /* Liste aller fertig gelinkten Klassen */
+
+
+
+/***************** die Referenzen auf die wichtigen Systemklassen ************/
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_ClassCastException;
+classinfo *class_java_lang_NullPointerException;
+classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
+classinfo *class_java_lang_NegativeArraySizeException;
+classinfo *class_java_lang_OutOfMemoryError;
+classinfo *class_java_lang_ArithmeticException;
+classinfo *class_java_lang_ArrayStoreException;
+classinfo *class_java_lang_ThreadDeath;                 /* schani */
+
+classinfo *class_array;
+
+
+/************ einige vorgefertigte Instanzen wichtiger Systemklassen *********/
+
+java_objectheader *proto_java_lang_ClassCastException;
+java_objectheader *proto_java_lang_NullPointerException;
+java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
+java_objectheader *proto_java_lang_NegativeArraySizeException;
+java_objectheader *proto_java_lang_OutOfMemoryError;
+java_objectheader *proto_java_lang_ArithmeticException;
+java_objectheader *proto_java_lang_ArrayStoreException;
+java_objectheader *proto_java_lang_ThreadDeath;         /* schani */
+
+
+
+
+/****************************************************************************/
+/******************* Einige Support-Funkionen *******************************/
+/****************************************************************************/
+
+
+/********** interne Funktion: printflags  (nur zu Debug-Zwecken) ************/
+
+static void printflags (u2 f)
+{
+   if ( f & ACC_PUBLIC )       printf (" PUBLIC");
+   if ( f & ACC_PRIVATE )      printf (" PRIVATE");
+   if ( f & ACC_PROTECTED )    printf (" PROTECTED");
+   if ( f & ACC_STATIC )       printf (" STATIC");
+   if ( f & ACC_FINAL )        printf (" FINAL");
+   if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
+   if ( f & ACC_VOLATILE )     printf (" VOLATILE");
+   if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
+   if ( f & ACC_NATIVE )       printf (" NATIVE");
+   if ( f & ACC_INTERFACE )    printf (" INTERFACE");
+   if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
+}
+
+
+/************************* Funktion: skipattribute ****************************
+
+       "uberliest im ClassFile eine (1) 'attribute'-Struktur 
+
+******************************************************************************/
+
+static void skipattribute ()
+{
+       u4 len;
+
+       suck_u2 ();
+       len = suck_u4 ();
+       skip_nbytes (len);      
+}
+
+/********************** Funktion: skipattributebody ***************************
+
+       "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
+       Referenz schon gelesen worden ist.
+       
+******************************************************************************/
+
+static void skipattributebody ()
+{
+       u4 len = suck_u4 ();
+       skip_nbytes (len);
+}
+
+
+/************************* Funktion: skipattributes ***************************
+
+       "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
+       
+******************************************************************************/
+
+static void skipattributes (u4 num)
+{
+       u4 i;
+       for (i=0; i<num; i++) skipattribute();
+}
+
+
+
+/************************** Funktion: loadUtf8 ********************************
+
+       liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text) 
+       und legt daf"ur ein unicode-Symbol an. 
+       Return: Zeiger auf das Symbol 
+
+******************************************************************************/
+
+#define MAXUNICODELEN 5000
+static u2 unicodebuffer[MAXUNICODELEN];
+
+static unicode *loadUtf8 ()
+{
+       u4 unicodelen;
+       u4 letter;
+
+       u4 utflen;
+       u4 b1,b2,b3;
+
+       unicodelen = 0;
+
+       utflen = suck_u2 ();
+       while (utflen > 0) {
+               b1 = suck_u1 ();
+               utflen --;
+               if (b1<0x80) letter = b1;
+               else {
+                       b2 = suck_u1 ();
+                       utflen --;
+                       if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
+                       else {
+                               b3 = suck_u1 ();
+                               utflen --;
+                               letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
+                               }
+                       }       
+       
+
+               if (unicodelen >= MAXUNICODELEN) {
+                       panic ("String constant too long");
+                       }
+               
+               unicodebuffer[unicodelen++] = letter;                   
+               }
+
+       
+       return unicode_new_u2 (unicodebuffer, unicodelen);
+}
+
+
+
+/******************** interne Funktion: checkfieldtype ***********************/
+
+static void checkfieldtype (u2 *text, u4 *count, u4 length)
+{
+       u4 l;
+
+       if (*count >= length) panic ("Type-descriptor exceeds unicode length");
+       
+       l = text[(*count)++];
+       
+       switch (l) {
+               default: panic ("Invalid symbol in type descriptor");
+                        return;
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'F':
+               case 'I':
+               case 'J':
+               case 'S':
+               case 'Z': return;
+               
+               case '[': checkfieldtype (text, count, length);
+                         return;
+                         
+               case 'L': 
+                       {
+                       u4 tlen,tstart = *count;
+                       
+                       if (*count >= length) 
+                          panic ("Objecttype descriptor of length zero");
+                       
+                       while ( text[*count] != ';' ) {
+                               (*count)++;
+                               if (*count >= length) 
+                                  panic ("Missing ';' in objecttype-descriptor");
+                               }
+                       
+                       tlen = (*count) - tstart;
+                       (*count)++;
+
+                       if (tlen == 0) panic ("Objecttype descriptor with empty name");
+                                       
+                       class_get ( unicode_new_u2 (text+tstart, tlen) );
+                       }
+               }       
+}
+
+
+/******************* Funktion: checkfielddescriptor ***************************
+
+       "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
+       Wenn nicht, dann wird das System angehalten.
+       Au"serdem werden alle Klassen, die hier referenziert werden, 
+       in die Liste zu ladender Klassen eingetragen.
+       
+******************************************************************************/
+
+void checkfielddescriptor (unicode *d)
+{
+       u4 count=0;
+       checkfieldtype (d->text, &count, d->length);
+       if (count != d->length) panic ("Invalid type-descritor encountered");
+}
+
+
+/******************* Funktion: checkmethoddescriptor **************************
+
+       "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
+       Wenn nicht, dann wird das System angehalten.
+       Au"serdem werden alle Klassen, die hier referenziert werden, 
+       in die Liste zu ladender Klassen eingetragen.
+       
+******************************************************************************/
+
+void checkmethoddescriptor (unicode *d)
+{
+       u2 *text=d->text;
+       u4 length=d->length;
+       u4 count=0;
+       
+       if (length<2) panic ("Method descriptor too short");
+       if (text[0] != '(') panic ("Missing '(' in method descriptor");
+       count=1;
+       
+       while (text[count] != ')') {
+               checkfieldtype (text,&count,length);
+               if ( count > length-2 ) panic ("Unexpected end of descriptor");
+               }
+               
+       count++;
+       if (text[count] == 'V') count++;
+       else                    checkfieldtype (text, &count,length);
+               
+       if (count != length) panic ("Method-descriptor has exceeding chars");
+}
+
+
+/******************** Funktion: buildarraydescriptor ****************************
+
+       erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
+       entsprechende constant_arraydescriptor - Struktur 
+       
+********************************************************************************/
+
+static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
+{
+       constant_arraydescriptor *d;
+       
+       if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
+       d = NEW (constant_arraydescriptor);
+       d -> objectclass = NULL;
+       d -> elementdescriptor = NULL;
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_arraydescriptor);
+#endif
+
+       switch (name[1]) {
+       case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
+       case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
+       case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
+       case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
+       case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
+       case 'I': d -> arraytype = ARRAYTYPE_INT; break;
+       case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
+       case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
+
+       case '[':
+               d -> arraytype = ARRAYTYPE_ARRAY; 
+               d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
+               break;
+               
+       case 'L':
+               d -> arraytype = ARRAYTYPE_OBJECT;
+               d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
+               break;
+       }
+       return d;
+}
+
+
+/******************* Funktion: freearraydescriptor ****************************
+
+       entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
+       aus dem Speicher
+       
+*******************************************************************************/
+
+static void freearraydescriptor (constant_arraydescriptor *d)
+{
+       while (d) {
+               constant_arraydescriptor *n = d->elementdescriptor;
+               FREE (d, constant_arraydescriptor);
+               d = n;
+               }
+}
+
+/*********************** Funktion: displayarraydescriptor *********************/
+
+static void displayarraydescriptor (constant_arraydescriptor *d)
+{
+       switch (d->arraytype) {
+       case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
+       case ARRAYTYPE_BYTE: printf ("byte[]"); break;
+       case ARRAYTYPE_CHAR: printf ("char[]"); break;
+       case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
+       case ARRAYTYPE_FLOAT: printf ("float[]"); break;
+       case ARRAYTYPE_INT: printf ("int[]"); break;
+       case ARRAYTYPE_LONG: printf ("long[]"); break;
+       case ARRAYTYPE_SHORT: printf ("short[]"); break;
+       case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
+       case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
+       }
+}
+
+
+
+/*****************************************************************************/
+/******************** Funktionen fuer Fields *********************************/
+/*****************************************************************************/
+
+
+/************************ Funktion: field_load ********************************
+
+       l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
+       und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
+       Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
+       reserviert.
+
+******************************************************************************/
+
+static void field_load (fieldinfo *f, classinfo *c)
+{
+       u4 attrnum,i;
+       u4 jtype;
+
+       f -> flags = suck_u2 ();
+       f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       f -> type = jtype = desc_to_type (f->descriptor);
+       f -> offset = 0;
+
+       switch (f->type) {
+       case TYPE_INT:        f->value.i = 0; break;
+       case TYPE_FLOAT:      f->value.f = 0.0; break;
+       case TYPE_DOUBLE:     f->value.d = 0.0; break;
+       case TYPE_ADDRESS:    f->value.a = NULL; 
+                             heap_addreference (&(f->value.a));
+                             break;
+       case TYPE_LONG:
+#if U8_AVAILABLE
+               f->value.l = 0; break;
+#else
+               f->value.l.low = 0; f->value.l.high = 0; break;
+#endif 
+       }
+       
+       attrnum = suck_u2();
+       for (i=0; i<attrnum; i++) {
+               u4 pindex;
+               unicode *aname;
+
+               aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+               if ( aname != unicode_new_char ("ConstantValue") ) {
+                       skipattributebody ();
+                       }
+               else {
+                       suck_u4();
+                       pindex = suck_u2();
+                               
+                       switch (jtype) {
+                               case TYPE_INT: {
+                                       constant_integer *ci = 
+                                               class_getconstant(c, pindex, CONSTANT_Integer);
+                                       f->value.i = ci -> value;
+                                       }
+                                       break;
+                                       
+                               case TYPE_LONG: {
+                                       constant_long *cl = 
+                                          class_getconstant(c, pindex, CONSTANT_Long);
+       
+                                       f->value.l = cl -> value;
+                                       }
+                                       break;
+
+                               case TYPE_FLOAT: {
+                                       constant_float *cf = 
+                                           class_getconstant(c, pindex, CONSTANT_Float);
+       
+                                       f->value.f = cf->value;
+                                       }
+                                       break;
+                                                                                       
+                               case TYPE_DOUBLE: {
+                                       constant_double *cd = 
+                                           class_getconstant(c, pindex, CONSTANT_Double);
+       
+                                       f->value.d = cd->value;
+                                       }
+                                       break;
+                                               
+                               case TYPE_ADDRESS: {
+                                       unicode *u = 
+                                               class_getconstant(c, pindex, CONSTANT_String);
+                                       f->value.a = literalstring_new(u);
+                                       }
+                                       break;
+       
+                               default: 
+                                       log_text ("Invalid Constant - Type");
+
+                               }
+
+                       }
+               }
+               
+}
+
+
+/********************** Funktion: field_free *********************************/
+
+static void field_free (fieldinfo *f)
+{
+}
+
+
+/************** Funktion: field_display (nur zu Debug-Zwecken) ***************/
+
+static void field_display (fieldinfo *f)
+{
+       printf ("   ");
+       printflags (f -> flags);
+       printf (" ");
+       unicode_display (f -> name);
+       printf (" ");
+       unicode_display (f -> descriptor);      
+       printf (" offset: %ld\n", (long int) (f -> offset) );
+}
+
+
+
+
+/*****************************************************************************/
+/************************* Funktionen f"ur Methods ***************************/ 
+/*****************************************************************************/
+
+
+/*********************** Funktion: method_load ********************************
+
+       l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
+       eine schon existierende 'methodinfo'-Struktur aus.
+       Bei allen native-Methoden wird au"serdem gleich der richtige 
+       Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
+       Zeiger auf den Compiler 
+       
+******************************************************************************/
+
+static void method_load (methodinfo *m, classinfo *c)
+{
+       u4 attrnum,i,e;
+       
+#ifdef STATISTICS
+       count_all_methods++;
+#endif
+
+       m -> class = c;
+       
+       m -> flags = suck_u2 ();
+       m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+       
+       m -> jcode = NULL;
+       m -> exceptiontable = NULL;
+       m -> entrypoint = NULL;
+       m -> mcode = NULL;
+       m -> stubroutine = NULL;
+       
+       if (! (m->flags & ACC_NATIVE) ) {
+               m -> stubroutine = createcompilerstub (m);
+               }
+       else {
+               functionptr f = native_findfunction 
+                      (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
+               if (f) {
+               if (newcompiler)
+                       m -> stubroutine = ncreatenativestub (f, m);
+               else
+                       m -> stubroutine = createnativestub (f, m);
+                       }
+               }
+       
+       
+       attrnum = suck_u2();
+       for (i=0; i<attrnum; i++) {
+               unicode *aname;
+
+               aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
+
+               if ( aname != unicode_new_char("Code"))  {
+                       skipattributebody ();
+                       }
+               else {
+                       if (m -> jcode) panic ("Two code-attributes for one method!");
+                       
+                       suck_u4();
+                       m -> maxstack = suck_u2();
+                       m -> maxlocals = suck_u2();
+                       m -> jcodelength = suck_u4();
+                       m -> jcode = MNEW (u1, m->jcodelength);
+                       suck_nbytes (m->jcode, m->jcodelength);
+                       m -> exceptiontablelength = suck_u2 ();
+                       m -> exceptiontable = 
+                          MNEW (exceptiontable, m->exceptiontablelength);
+
+#ifdef STATISTICS
+       count_vmcode_len += m->jcodelength + 18;
+       count_extable_len += 8 * m->exceptiontablelength;
+#endif
+
+                       for (e=0; e < m->exceptiontablelength; e++) {
+                               u4 idx;
+                               m -> exceptiontable[e].startpc = suck_u2();
+                               m -> exceptiontable[e].endpc = suck_u2();
+                               m -> exceptiontable[e].handlerpc = suck_u2();
+
+                               idx = suck_u2();
+                               if (!idx) m -> exceptiontable[e].catchtype = NULL;
+                               else {
+                                       m -> exceptiontable[e].catchtype = 
+                                     class_getconstant (c, idx, CONSTANT_Class);
+                                       }
+                               }                       
+
+                       skipattributes ( suck_u2() );
+                       }
+                       
+               }
+
+
+}
+
+
+/********************* Funktion: method_free **********************************
+
+       gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
+       wieder frei
+
+******************************************************************************/
+
+static void method_free (methodinfo *m)
+{
+       if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
+       if (m->exceptiontable) 
+               MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
+       if (m->mcode) CFREE (m->mcode, m->mcodelength);
+       if (m->stubroutine) {
+               if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
+               else                       removecompilerstub (m->stubroutine);
+               }
+}
+
+
+/************** Funktion: method_display  (nur zu Debug-Zwecken) *************/
+
+void method_display (methodinfo *m)
+{
+       printf ("   ");
+       printflags (m -> flags);
+       printf (" ");
+       unicode_display (m -> name);
+       printf (" "); 
+       unicode_display (m -> descriptor);
+       printf ("\n");
+}
+
+
+/******************** Funktion: method_canoverwrite ***************************
+
+       "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
+       ist (also mit einer Methodendefinition eine andere "uberschrieben 
+       werden kann).
+       
+******************************************************************************/  
+
+static bool method_canoverwrite (methodinfo *m, methodinfo *old)
+{
+       if (m->name != old->name) return false;
+       if (m->descriptor != old->descriptor) return false;
+       if (m->flags & ACC_STATIC) return false;
+       return true;
+}
+
+
+
+
+/*****************************************************************************/
+/************************ Funktionen fuer Class ******************************/
+/*****************************************************************************/
+
+
+/******************** Funktion: class_get *************************************
+
+       Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
+       eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
+       ladenen Klassen ein).
+
+******************************************************************************/
+
+classinfo *class_get (unicode *u)
+{
+       classinfo *c;
+       
+       if (u->class) return u->class;
+       
+#ifdef STATISTICS
+       count_class_infos += sizeof(classinfo);
+#endif
+
+       c = NEW (classinfo);
+       c -> flags = 0;
+       c -> name = u;
+       c -> cpcount = 0;
+       c -> cptags = NULL;
+       c -> cpinfos = NULL;
+       c -> super = NULL;
+       c -> interfacescount = 0;
+       c -> interfaces = NULL;
+       c -> fieldscount = 0;
+       c -> fields = NULL;
+       c -> methodscount = 0;
+       c -> methods = NULL;
+       c -> linked = false;
+       c -> index = 0;
+       c -> instancesize = 0;
+       c -> vftbl = NULL;
+       c -> initialized = false;
+       
+       unicode_setclasslink (u,c);
+       list_addlast (&unloadedclasses, c);
+               
+       return c;
+}
+
+
+
+/******************** Funktion: class_getconstant *****************************
+
+       holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
+       Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
+
+******************************************************************************/
+
+voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
+{
+       if (pos >= c->cpcount) 
+               panic ("Attempt to access constant outside range");
+       if (c->cptags[pos] != ctype) {
+               sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
+                (int) ctype, (int) c->cptags[pos] );
+               error();
+               }
+               
+       return c->cpinfos[pos];
+}
+
+
+/********************* Funktion: class_constanttype ***************************
+
+       Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
+       Klasse hat.
+       
+******************************************************************************/
+
+u4 class_constanttype (classinfo *c, u4 pos)
+{
+       if (pos >= c->cpcount) 
+               panic ("Attempt to access constant outside range");
+       return c->cptags[pos];
+}
+
+
+/******************** Funktion: class_loadcpool *******************************
+
+       l"adt den gesammten ConstantPool einer Klasse.
+       
+       Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers 
+       Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
+       F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h' 
+
+******************************************************************************/
+
+static void class_loadcpool (classinfo *c)
+{
+
+       typedef struct forward_class {      /* Diese Strukturen dienen dazu, */
+               struct forward_class *next;     /* die Infos, die beim ersten */
+               u2 thisindex;                   /* Durchgang durch den ConstantPool */
+               u2 name_index;                  /* gelesen werden, aufzunehmen. */
+       } forward_class;                    /* Erst nachdem der ganze Pool */ 
+                                        /* gelesen wurde, k"onnen alle */
+       typedef struct forward_string {     /* Felder kompletiert werden */
+               struct forward_string *next;    /* (und das auch nur in der richtigen */
+               u2 thisindex;                   /* Reihenfolge) */
+               u2 string_index;
+       } forward_string;
+
+       typedef struct forward_nameandtype {
+               struct forward_nameandtype *next;
+               u2 thisindex;
+               u2 name_index;
+               u2 sig_index;
+       } forward_nameandtype;
+
+       typedef struct forward_fieldmethint {   
+               struct forward_fieldmethint *next;
+               u2 thisindex;
+               u1 tag;
+               u2 class_index;
+               u2 nameandtype_index;
+       } forward_fieldmethint;
+
+
+
+       u4 idx;
+       long int dumpsize = dump_size ();
+
+       forward_class *forward_classes = NULL;
+       forward_string *forward_strings = NULL;
+       forward_nameandtype *forward_nameandtypes = NULL;
+       forward_fieldmethint *forward_fieldmethints = NULL;
+
+       u4 cpcount       = c -> cpcount = suck_u2();
+       u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
+       voidptr *cpinfos = c -> cpinfos =  MNEW (voidptr, cpcount);
+
+#ifdef STATISTICS
+       count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#endif
+
+       
+       for (idx=0; idx<cpcount; idx++) {
+               cptags[idx] = CONSTANT_UNUSED;
+               cpinfos[idx] = NULL;
+               }
+
+                       
+               /******* Erster Durchgang *******/
+               /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen, 
+                  werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
+                  und dann am Ende nocheinmal durchgegangen */
+
+       idx = 1;
+       while (idx < cpcount) {
+               u4 t = suck_u1 ();
+               switch ( t ) {
+
+                       case CONSTANT_Class: { 
+                               forward_class *nfc = DNEW(forward_class);
+
+                               nfc -> next = forward_classes;                                                                                  
+                               forward_classes = nfc;
+
+                               nfc -> thisindex = idx;
+                               nfc -> name_index = suck_u2 ();
+
+                               idx++;
+                               break;
+                               }
+                       
+                       case CONSTANT_Fieldref:
+                       case CONSTANT_Methodref:
+                       case CONSTANT_InterfaceMethodref: {
+                               forward_fieldmethint *nff = DNEW (forward_fieldmethint);
+                               
+                               nff -> next = forward_fieldmethints;
+                               forward_fieldmethints = nff;
+
+                               nff -> thisindex = idx;
+                               nff -> tag = t;
+                               nff -> class_index = suck_u2 ();
+                               nff -> nameandtype_index = suck_u2 ();
+
+                               idx ++;                                         
+                               break;
+                               }
+                               
+                       case CONSTANT_String: {
+                               forward_string *nfs = DNEW (forward_string);
+                               
+                               nfs -> next = forward_strings;
+                               forward_strings = nfs;
+                               
+                               nfs -> thisindex = idx;
+                               nfs -> string_index = suck_u2 ();
+                               
+                               idx ++;
+                               break;
+                               }
+
+                       case CONSTANT_NameAndType: {
+                               forward_nameandtype *nfn = DNEW (forward_nameandtype);
+                               
+                               nfn -> next = forward_nameandtypes;
+                               forward_nameandtypes = nfn;
+                               
+                               nfn -> thisindex = idx;
+                               nfn -> name_index = suck_u2 ();
+                               nfn -> sig_index = suck_u2 ();
+                               
+                               idx ++;
+                               break;
+                               }
+
+                       case CONSTANT_Integer: {
+                               constant_integer *ci = NEW (constant_integer);
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_integer);
+#endif
+
+                               ci -> value = suck_s4 ();
+                               cptags [idx] = CONSTANT_Integer;
+                               cpinfos [idx] = ci;
+                               idx ++;
+                               
+                               break;
+                               }
+                               
+                       case CONSTANT_Float: {
+                               constant_float *cf = NEW (constant_float);
+
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_float);
+#endif
+
+                               cf -> value = suck_float ();
+                               cptags [idx] = CONSTANT_Float;
+                               cpinfos[idx] = cf;
+                               idx ++;
+                               break;
+                               }
+                               
+                       case CONSTANT_Long: {
+                               constant_long *cl = NEW(constant_long);
+                                       
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_long);
+#endif
+
+                               cl -> value = suck_s8 ();
+                               cptags [idx] = CONSTANT_Long;
+                               cpinfos [idx] = cl;
+                               idx += 2;
+                               break;
+                               }
+                       
+                       case CONSTANT_Double: {
+                               constant_double *cd = NEW(constant_double);
+                               
+#ifdef STATISTICS
+       count_const_pool_len += sizeof(constant_double);
+#endif
+
+                               cd -> value = suck_double ();
+                               cptags [idx] = CONSTANT_Double;
+                               cpinfos [idx] = cd;
+                               idx += 2;
+                               break;
+                               }
+                               
+                       case CONSTANT_Utf8: {
+                               unicode *u;
+
+                               u = loadUtf8 ();
+
+                               cptags [idx] = CONSTANT_Utf8;
+                               cpinfos [idx] = u;
+                               idx++;
+                               break;
+                               }
+                                                                               
+                       default:
+                               sprintf (logtext, "Unkown constant type: %d",(int) t);
+                               error ();
+               
+                       }  /* end switch */
+                       
+               } /* end while */
+               
+
+
+          /* Aufl"osen der noch unfertigen Eintr"age */
+
+       while (forward_classes) {
+               unicode *name =
+                 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
+               
+               if ( (name->length>0) && (name->text[0]=='[') ) {
+                       checkfielddescriptor (name); 
+
+                       cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
+                       cpinfos [forward_classes -> thisindex] = 
+                          buildarraydescriptor(name->text, name->length);
+
+                       }
+               else {          
+                       cptags  [forward_classes -> thisindex] = CONSTANT_Class;
+                       cpinfos [forward_classes -> thisindex] = class_get (name);
+                       }
+               forward_classes = forward_classes -> next;
+               
+               }
+
+       while (forward_strings) {
+               unicode *text = 
+                 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
+                       
+               cptags   [forward_strings -> thisindex] = CONSTANT_String;
+               cpinfos  [forward_strings -> thisindex] = text;
+               
+               forward_strings = forward_strings -> next;
+               }       
+
+       while (forward_nameandtypes) {
+               constant_nameandtype *cn = NEW (constant_nameandtype);  
+
+#ifdef STATISTICS
+               count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+               cn -> name = class_getconstant 
+                  (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
+               cn -> descriptor = class_getconstant
+                  (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
+                
+               cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
+               cpinfos  [forward_nameandtypes -> thisindex] = cn;
+               
+               forward_nameandtypes = forward_nameandtypes -> next;
+               }
+
+
+       while (forward_fieldmethints)  {
+               constant_nameandtype *nat;
+               constant_FMIref *fmi = NEW (constant_FMIref);
+
+#ifdef STATISTICS
+               count_const_pool_len += sizeof(constant_FMIref);
+#endif
+
+               nat = class_getconstant
+                       (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
+
+               fmi -> class = class_getconstant 
+                       (c, forward_fieldmethints -> class_index, CONSTANT_Class);
+               fmi -> name = nat -> name;
+               fmi -> descriptor = nat -> descriptor;
+
+               cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
+               cpinfos [forward_fieldmethints -> thisindex] = fmi;
+       
+               switch (forward_fieldmethints -> tag) {
+               case CONSTANT_Fieldref:  checkfielddescriptor (fmi->descriptor);
+                                        break;
+               case CONSTANT_InterfaceMethodref: 
+               case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
+                                        break;
+               }               
+       
+               forward_fieldmethints = forward_fieldmethints -> next;
+
+               }
+
+
+       dump_release (dumpsize);
+}
+
+
+/********************** Funktion: class_load **********************************
+
+       l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
+       'classinfo'-Struktur mu"s bereits angelegt worden sein.
+       
+       Die Superklasse und die Interfaces, die diese Klasse implementiert,
+       m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
+       Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
+       
+       Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
+       und in die Liste 'unlinkedclasses' eingh"angt.
+       
+******************************************************************************/
+
+static void class_load (classinfo *c)
+{
+       u4 i;
+       u4 mi,ma;
+
+
+       if (loadverbose) {
+               sprintf (logtext, "Loading class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name );
+               dolog();
+               }
+
+
+       suck_start (c->name);
+
+       if (suck_u4() != MAGIC) panic("Can not find class-file signature");   
+       mi = suck_u2(); 
+       ma = suck_u2();
+       if (ma != MAJOR_VERSION) {
+               sprintf (logtext, "Can only support major version %d, but not %d",
+                                MAJOR_VERSION, (int) ma);
+               error();
+               }
+       if (mi > MINOR_VERSION)  {
+               sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
+               error();
+               }
+
+
+       class_loadcpool (c);
+       
+       c -> flags = suck_u2 ();
+       suck_u2 ();       /* this */
+       
+       if ( (i = suck_u2 () ) ) {
+               c -> super = class_getconstant (c, i, CONSTANT_Class);
+               }
+       else {
+               c -> super = NULL;
+               }
+                        
+       c -> interfacescount = suck_u2 ();
+       c -> interfaces = MNEW (classinfo*, c -> interfacescount);
+       for (i=0; i < c -> interfacescount; i++) {
+               c -> interfaces [i] = 
+                     class_getconstant (c, suck_u2(), CONSTANT_Class);
+               }
+
+       c -> fieldscount = suck_u2 ();
+       c -> fields = MNEW (fieldinfo, c -> fieldscount);
+       for (i=0; i < c -> fieldscount; i++) {
+               field_load (&(c->fields[i]), c);
+               }
+
+       c -> methodscount = suck_u2 ();
+       c -> methods = MNEW (methodinfo, c -> methodscount);
+       for (i=0; i < c -> methodscount; i++) {
+               method_load (&(c -> methods [i]), c);
+               }
+
+#ifdef STATISTICS
+       count_class_infos += sizeof(classinfo*) * c -> interfacescount;
+       count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
+       count_class_infos += sizeof(methodinfo) * c -> methodscount;
+#endif
+
+
+       skipattributes ( suck_u2() );
+
+
+       suck_stop ();
+
+       list_remove (&unloadedclasses, c);
+       list_addlast (&unlinkedclasses, c);
+}
+
+
+
+/************** interne Funktion: class_highestinterface **********************
+
+       wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
+       die Interfacetable einer Klasse sein mu"s.
+
+******************************************************************************/
+
+static s4 class_highestinterface (classinfo *c) 
+{
+       s4 h;
+       s4 i;
+       
+       if ( ! (c->flags & ACC_INTERFACE) ) {
+               sprintf (logtext, "Interface-methods count requested for non-interface:  ");
+       unicode_sprint (logtext+strlen(logtext), c->name);
+       error();
+       }
+    
+    h = c->index;
+       for (i=0; i<c->interfacescount; i++) {
+               s4 h2 = class_highestinterface (c->interfaces[i]);
+               if (h2>h) h=h2;
+               }
+       return h;
+}
+
+
+/**************** Funktion: class_addinterface ********************************
+
+       wird von der Funktion class_link ben"otigt, um eine Virtual Function 
+       Table f"ur ein Interface (und alle weiteren von diesem Interface
+       implementierten Interfaces) in eine Klasse einzutragen.
+
+******************************************************************************/        
+
+static void class_addinterface (classinfo *c, classinfo *ic)
+{
+       u4 i = ic->index;
+       u4 j,m;
+       vftbl *vftbl = c->vftbl;
+       
+       if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
+       if (vftbl->interfacevftbl[i]) return;
+
+       if (ic->methodscount==0) {  /* wenn interface keine Methoden hat, dann 
+                                      trotzdem eine Tabelle mit L"ange 1 anlegen,
+                                      wegen Subclass-Tests */
+               vftbl -> interfacevftbllength[i] = 1;
+               vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
+               vftbl -> interfacevftbl[i][0] = NULL;
+               }
+       else {
+               vftbl -> interfacevftbllength[i] = ic -> methodscount;
+               vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount); 
+
+#ifdef STATISTICS
+       count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
+#endif
+
+               for (j=0; j<ic->methodscount; j++) {
+                       classinfo *sc = c;
+                       while (sc) {
+                               for (m=0; m<sc->methodscount; m++) {
+                                       methodinfo *mi = &(sc->methods[m]);
+                                       if (method_canoverwrite (mi, &(ic->methods[j])) ) {
+                                               vftbl->interfacevftbl[i][j] = 
+                                                        vftbl->table[mi->vftblindex];
+                                               goto foundmethod;
+                                               }
+                                       }
+                               sc = sc->super;
+                               }
+                        foundmethod: ;
+                       }
+               }
+               
+       for (j=0; j<ic->interfacescount; j++) 
+               class_addinterface(c, ic->interfaces[j]);
+}
+
+
+/********************** Funktion: class_link **********************************
+
+       versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
+       m"ussen sowol die Superklasse, als auch alle implementierten
+       Interfaces schon gelinkt sein.
+       Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
+       dieser Klasse, als auch die Virtual Function Tables f"ur normale
+       Methoden als auch Interface-Methoden.
+       
+       Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
+       der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
+       eingetragen.
+       Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
+
+       Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
+                eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
+
+******************************************************************************/
+
+static void class_link (classinfo *c)
+{
+       u4 supervftbllength;          /* L"ange der VFTBL der Superklasse */
+       u4 vftbllength;               /* L"ange der VFTBL dieser Klasse */
+       classinfo *super = c->super;  
+       classinfo *ic,*c2;            /* Hilfsvariablen */
+       vftbl *v;
+       u4 i;                          
+
+
+               /* schauen, ob alle "ubergeordneten Klassen schon fertig sind, 
+                  und richtiges Initialisieren der lokalen Variablen */ 
+
+       for ( i=0; i<c->interfacescount; i++) {
+               ic = c->interfaces[i];
+               if ( !ic -> linked) {
+                       list_remove (&unlinkedclasses,c );
+                       list_addlast (&unlinkedclasses,c );
+                       return; 
+                       }
+               }
+       
+       if (! super) {
+               c -> index = 0;
+               c -> instancesize = sizeof (java_objectheader);
+               
+               vftbllength = supervftbllength = 0;
+
+               c -> finalizer = NULL;
+               }
+       else {
+               if ( !super -> linked ) {
+                       list_remove (&unlinkedclasses,c );
+                       list_addlast (&unlinkedclasses,c );
+                       return; 
+                       }
+
+               if ( c->flags & ACC_INTERFACE)     c -> index = interfaceindex++;
+                                       else       c -> index = super -> index + 1;
+               
+               c -> instancesize = super -> instancesize;
+               
+               vftbllength = supervftbllength = super -> vftbl -> vftbllength;
+               
+               c -> finalizer = super -> finalizer;
+               }
+
+
+       if (linkverbose) {
+               sprintf (logtext, "Linking Class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name );
+               dolog ();
+               }
+
+               /* Erstellen der Virtual Function Table */
+
+       for (i=0; i < c->methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+                       
+               if (! (m->flags & ACC_STATIC) ) {
+                       classinfo *sc = super;
+                       while (sc) {
+                               int j;
+                               for (j=0; j < sc->methodscount; j++) {
+                                       if ( method_canoverwrite (m, &(sc->methods[j])) ) {
+                                               m -> vftblindex = sc->methods[j].vftblindex;
+                                               goto foundvftblindex;
+                                               }
+                                       }
+                               sc = sc->super;
+                               }
+                       m -> vftblindex = (vftbllength++);
+                 foundvftblindex: ;
+                       }
+               }       
+       
+#ifdef STATISTICS
+       count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
+#endif
+
+       c -> vftbl = v = (vftbl*) 
+            mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
+       v -> class = c;
+       v -> vftbllength = vftbllength;
+       v -> interfacetablelength = 0;
+       
+       for (i=0; i < supervftbllength; i++) 
+          v -> table[i] = super -> vftbl -> table[i];
+       
+       for (i=0; i < c->methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+               if ( ! (m->flags & ACC_STATIC) ) {
+                       v -> table[m->vftblindex] = m -> stubroutine;
+                       }
+               }
+
+
+               /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen 
+                  Felder */
+       
+       for (i=0; i < c->fieldscount; i++) {
+               u4 dsize;
+               fieldinfo *f = &(c -> fields[i]);
+               
+               if ( ! (f->flags & ACC_STATIC) ) {
+                       dsize = desc_typesize (f->descriptor);
+                       c -> instancesize = ALIGN ( c->instancesize, dsize);
+                       f -> offset = c -> instancesize;
+                       c -> instancesize += dsize;
+                       }
+
+               }
+
+       
+               /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
+       
+       c2 = c;
+       while (c2) {
+               for (i=0; i<c2->interfacescount; i++) {
+                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+                       if ( h > v->interfacetablelength) v->interfacetablelength = h;
+                       }
+               c2 = c2->super;
+               }
+       v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
+       v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength); 
+
+#ifdef STATISTICS
+       count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
+#endif
+
+       for (i=0; i < v->interfacetablelength; i++) {
+               v -> interfacevftbllength[i] = 0;
+               v -> interfacevftbl[i] = NULL;
+               }
+       
+       c2 = c;
+       while (c2) {
+               for (i=0; i<c2->interfacescount; i++) {
+                       class_addinterface (c, c2->interfaces[i]);
+                       }
+               c2 = c2->super;
+               }
+               
+
+
+               /* Die finalizer-Methode suchen und eintragen (wenn vorhanden), 
+                  aber nur bei Objekten ausser java.lang.Object */
+
+       if (super) {
+               methodinfo *fi;
+               static unicode *finame=NULL,*fidesc=NULL;
+               
+               if (!finame) finame = unicode_new_char ("finalize");
+               if (!fidesc) fidesc = unicode_new_char ("()V");
+
+               fi = class_findmethod (c, finame, fidesc);
+               if (fi) {
+                       if (! (fi->flags & ACC_STATIC) ) {
+                               c -> finalizer = fi;
+                               }
+                       }
+       }
+       
+       
+               /* Abschlie"sende Aktionen */
+       
+       c -> linked = true;     
+
+       list_remove (&unlinkedclasses, c);
+       list_addlast (&linkedclasses, c);
+}
+
+
+/******************* Funktion: class_freepool *********************************
+
+       Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
+       wieder frei.
+
+******************************************************************************/
+
+static void class_freecpool (classinfo *c)
+{
+       u4 idx;
+       u4 tag;
+       voidptr info;
+       
+       for (idx=0; idx < c->cpcount; idx++) {
+               tag = c->cptags[idx];
+               info = c->cpinfos[idx];
+               
+               if (info != NULL) {
+                       switch (tag) {
+                       case CONSTANT_Fieldref:
+                       case CONSTANT_Methodref:
+                       case CONSTANT_InterfaceMethodref:
+                               FREE (info, constant_FMIref);
+                               break;
+                       case CONSTANT_Integer:
+                               FREE (info, constant_integer);
+                               break;
+                       case CONSTANT_Float:
+                               FREE (info, constant_float);
+                               break;
+                       case CONSTANT_Long:
+                               FREE (info, constant_long);
+                               break;
+                       case CONSTANT_Double:
+                               FREE (info, constant_double);
+                               break;
+                       case CONSTANT_NameAndType:
+                               FREE (info, constant_nameandtype);
+                               break;
+                       case CONSTANT_Arraydescriptor:
+                               freearraydescriptor (info);
+                               break;
+                       }
+                       }
+               }
+
+       MFREE (c -> cptags,  u1, c -> cpcount);
+       MFREE (c -> cpinfos, voidptr, c -> cpcount);
+}
+
+
+/*********************** Funktion: class_free *********************************
+
+       Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
+
+******************************************************************************/
+
+static void class_free (classinfo *c)
+{
+       u4 i;
+       vftbl *v;
+               
+       unicode_unlinkclass (c->name);
+       
+       class_freecpool (c);
+
+       MFREE (c->interfaces, classinfo*, c->interfacescount);
+
+       for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
+       MFREE (c->fields, fieldinfo, c->fieldscount);
+       
+       for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
+       MFREE (c->methods, methodinfo, c->methodscount);
+
+       if ( (v = c->vftbl) ) {
+               for (i=0; i<v->interfacetablelength; i++) {
+                       MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
+                       }
+               MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
+               MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
+
+               mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
+               }
+               
+       FREE (c, classinfo);
+}
+
+
+/************************* Funktion: class_findfield *************************
+       
+       sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
+       Namen und Typ.
+
+*****************************************************************************/
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
+{
+       u4 i;
+       for (i=0; i < c->fieldscount; i++) {
+               if ( (c->fields[i].name == name)  &&  (c->fields[i].descriptor == desc) )
+                       return &(c->fields[i]);
+               }
+       panic ("Can not find field given in CONSTANT_Fieldref");
+       return NULL;
+}
+
+
+/************************* Funktion: class_findmethod *************************
+       
+       sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
+       Namen und Typ.
+       Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
+
+*****************************************************************************/
+
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
+{
+       u4 i;
+       for (i=0; i < c->methodscount; i++) {
+               if (     (c->methods[i].name == name)  
+                         && (    (desc == NULL) 
+                             ||  (c->methods[i].descriptor == desc) 
+                            )  
+                  )
+                       return &(c->methods[i]);
+               }
+       return NULL;
+}
+
+
+/************************* Funktion: class_resolvemethod *************************
+       
+       sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
+
+*****************************************************************************/
+
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
+{
+       while (c) {
+               methodinfo *m = class_findmethod (c, name, desc);
+               if (m) return m;
+               c = c->super;
+               }
+       return NULL;
+}
+       
+
+
+/************************* Funktion: class_issubclass ************************
+
+       "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
+       
+*****************************************************************************/
+
+bool class_issubclass (classinfo *sub, classinfo *super)
+{
+       for (;;) {
+               if (!sub) return false;
+               if (sub==super) return true;
+               sub = sub -> super;
+               }
+}
+
+
+
+/****************** Initialisierungsfunktion f"ur eine Klasse ****************
+
+       In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
+       Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
+       Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
+       wird.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+extern int blockInts;
+#endif
+
+void class_init (classinfo *c)
+{
+       methodinfo *m;
+       java_objectheader *exceptionptr;
+       s4 i;
+       int b;
+
+       if (!makeinitializations) return;
+       if (c->initialized) return;
+       c -> initialized = true;
+       
+       if (c->super) class_init (c->super);
+       for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
+
+       m = class_findmethod (c, 
+                             unicode_new_char ("<clinit>"), 
+                             unicode_new_char ("()V"));
+       if (!m) {
+               if (initverbose) {
+                       sprintf (logtext, "Class ");
+                       unicode_sprint (logtext+strlen(logtext), c->name);
+                       sprintf (logtext+strlen(logtext), " has no initializer");       
+                       dolog ();
+                       }
+               return;
+               }
+               
+       if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
+       
+       if (initverbose) {
+               sprintf (logtext, "Starting initializer for class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name);
+               dolog ();
+       }
+
+#ifdef USE_THREADS
+       b = blockInts;
+       blockInts = 0;
+#endif
+
+       exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
+
+#ifdef USE_THREADS
+       assert(blockInts == 0);
+       blockInts = b;
+#endif
+
+       if (exceptionptr) {     
+               printf ("#### Initializer has thrown: ");
+               unicode_display (exceptionptr->vftbl->class->name);
+               printf ("\n");
+               fflush (stdout);
+               }
+
+       if (initverbose) {
+               sprintf (logtext, "Finished initializer for class: ");
+               unicode_sprint (logtext+strlen(logtext), c->name);
+               dolog ();
+       }
+
+}
+
+
+
+
+/********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) ********/
+
+void class_showconstantpool (classinfo *c) 
+{
+       u4 i;
+       voidptr e;
+
+       printf ("---- dump of constant pool ----\n");
+
+       for (i=0; i<c->cpcount; i++) {
+               printf ("#%d:  ", (int) i);
+               
+               e = c -> cpinfos [i];
+               if (e) {
+                       
+                       switch (c -> cptags [i]) {
+                               case CONSTANT_Class:
+                                       printf ("Classreference -> ");
+                                       unicode_display ( ((classinfo*)e) -> name );
+                                       break;
+                               
+                               case CONSTANT_Fieldref:
+                                       printf ("Fieldref -> "); goto displayFMI;
+                               case CONSTANT_Methodref:
+                                       printf ("Methodref -> "); goto displayFMI;
+                               case CONSTANT_InterfaceMethodref:
+                                       printf ("InterfaceMethod -> "); goto displayFMI;
+                                 displayFMI:
+                                       {
+                                       constant_FMIref *fmi = e;
+                                       unicode_display ( fmi->class->name );
+                                       printf (".");
+                                       unicode_display ( fmi->name);
+                                       printf (" ");
+                                       unicode_display ( fmi->descriptor );
+                                   }
+                                       break;
+
+                               case CONSTANT_String:
+                                       printf ("String -> ");
+                                       unicode_display (e);
+                                       break;
+                               case CONSTANT_Integer:
+                                       printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+                                       break;
+                               case CONSTANT_Float:
+                                       printf ("Float -> %f", ((constant_float*)e) -> value);
+                                       break;
+                               case CONSTANT_Double:
+                                       printf ("Double -> %f", ((constant_double*)e) -> value);
+                                       break;
+                               case CONSTANT_Long:
+                                       {
+                                       u8 v = ((constant_long*)e) -> value;
+#if U8_AVAILABLE
+                                       printf ("Long -> %ld", (long int) v);
+#else
+                                       printf ("Long -> HI: %ld, LO: %ld\n", 
+                                           (long int) v.high, (long int) v.low);
+#endif 
+                                       }
+                                       break;
+                               case CONSTANT_NameAndType:
+                                       { constant_nameandtype *cnt = e;
+                                         printf ("NameAndType: ");
+                                         unicode_display (cnt->name);
+                                         printf (" ");
+                                         unicode_display (cnt->descriptor);
+                                       }
+                                       break;
+                               case CONSTANT_Utf8:
+                                       printf ("Utf8 -> ");
+                                       unicode_display (e);
+                                       break;
+                               case CONSTANT_Arraydescriptor:  {
+                                       printf ("Arraydescriptor: ");
+                                       displayarraydescriptor (e);
+                                       }
+                                       break;
+                               default: 
+                                       panic ("Invalid type of ConstantPool-Entry");
+                               }
+                               
+                       }
+
+               printf ("\n");
+               }
+       
+}
+
+
+
+/********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) ************/
+
+void class_showmethods (classinfo *c)
+{
+       u4 i;
+       
+       printf ("--------- Fields and Methods ----------------\n");
+       printf ("Flags: ");     printflags (c->flags);  printf ("\n");
+
+       printf ("This: "); unicode_display (c->name); printf ("\n");
+       if (c->super) {
+               printf ("Super: "); unicode_display (c->super->name); printf ("\n");
+               }
+       printf ("Index: %d\n", c->index);
+       
+       printf ("interfaces:\n");       
+       for (i=0; i < c-> interfacescount; i++) {
+               printf ("   ");
+               unicode_display (c -> interfaces[i] -> name);
+               printf (" (%d)\n", c->interfaces[i] -> index);
+               }
+
+       printf ("fields:\n");           
+       for (i=0; i < c -> fieldscount; i++) {
+               field_display (&(c -> fields[i]));
+               }
+
+       printf ("methods:\n");
+       for (i=0; i < c -> methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+               if ( !(m->flags & ACC_STATIC)) 
+                       printf ("vftblindex: %d   ", m->vftblindex);
+
+               method_display ( m );
+
+               }
+
+       printf ("Virtual function table:\n");
+       for (i=0; i<c->vftbl->vftbllength; i++) {
+               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
+               }
+
+}
+
+
+
+/*****************************************************************************/
+/******************* Funktionen fuer den Class-loader generell ***************/
+/*****************************************************************************/
+
+
+/********************* Funktion: loader_load **********************************
+
+       l"adt und linkt die ge"unschte Klasse und alle davon 
+       referenzierten Klassen und Interfaces
+       Return: Einen Zeiger auf diese Klasse
+
+******************************************************************************/
+
+classinfo *loader_load (unicode *topname)
+{
+       classinfo *top;
+       classinfo *c;
+       long int starttime=0,stoptime=0;
+       
+       intsDisable();                           /* schani */
+
+       if (getloadingtime) starttime = getcputime();
+       
+       
+       top = class_get (topname);
+
+       while ( (c = list_first(&unloadedclasses)) ) {
+               class_load (c);
+               }
+
+       while ( (c = list_first(&unlinkedclasses)) ) {
+               class_link (c);
+               }
+
+       
+       synchronize_caches ();
+       
+
+
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime-starttime);
+               }
+               
+       intsRestore();                      /* schani */
+
+       return top;
+}
+
+
+/******************* interne Funktion: loader_createarrayclass ****************
+
+       Erzeugt (und linkt) eine Klasse f"ur die Arrays.
+       
+******************************************************************************/
+
+static classinfo *loader_createarrayclass ()
+{
+       classinfo *c;
+       c = class_get ( unicode_new_char ("The_Array_Class") );
+       
+       list_remove (&unloadedclasses, c);
+       list_addlast (&unlinkedclasses, c);
+       c -> super = class_java_lang_Object;
+       
+       class_link (c);
+       return c;
+}
+
+
+
+/********************** Funktion: loader_init *********************************
+
+       Initialisiert alle Listen und l"adt alle Klassen, die vom System
+       und vom Compiler direkt ben"otigt werden.
+
+******************************************************************************/
+void loader_init ()
+{
+       interfaceindex = 0;
+       
+       list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
+       list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
+       list_init (&linkedclasses, OFFSET(classinfo, listnode) );
+
+
+       class_java_lang_Object = 
+               loader_load ( unicode_new_char ("java/lang/Object") );
+       class_java_lang_String = 
+               loader_load ( unicode_new_char ("java/lang/String") );
+       class_java_lang_ClassCastException = 
+               loader_load ( unicode_new_char ("java/lang/ClassCastException") );
+       class_java_lang_NullPointerException = 
+               loader_load ( unicode_new_char ("java/lang/NullPointerException") );
+       class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
+            unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
+       class_java_lang_NegativeArraySizeException = loader_load ( 
+            unicode_new_char ("java/lang/NegativeArraySizeException") );
+       class_java_lang_OutOfMemoryError = loader_load ( 
+            unicode_new_char ("java/lang/OutOfMemoryError") );
+       class_java_lang_ArrayStoreException =
+               loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
+       class_java_lang_ArithmeticException = 
+               loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
+       class_java_lang_ThreadDeath =                             /* schani */
+               loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
+
+       class_array = loader_createarrayclass ();
+
+
+       proto_java_lang_ClassCastException = 
+               builtin_new(class_java_lang_ClassCastException);
+       heap_addreference ( (void**) &proto_java_lang_ClassCastException);
+
+       proto_java_lang_NullPointerException = 
+               builtin_new(class_java_lang_NullPointerException);
+       heap_addreference ( (void**) &proto_java_lang_NullPointerException);
+
+       proto_java_lang_ArrayIndexOutOfBoundsException = 
+               builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
+       heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
+
+       proto_java_lang_NegativeArraySizeException = 
+               builtin_new(class_java_lang_NegativeArraySizeException);
+       heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
+
+       proto_java_lang_OutOfMemoryError = 
+               builtin_new(class_java_lang_OutOfMemoryError);
+       heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
+
+       proto_java_lang_ArithmeticException = 
+               builtin_new(class_java_lang_ArithmeticException);
+       heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
+
+       proto_java_lang_ArrayStoreException = 
+               builtin_new(class_java_lang_ArrayStoreException);
+       heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
+
+       proto_java_lang_ThreadDeath =                             /* schani */
+               builtin_new(class_java_lang_ThreadDeath);
+       heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
+}
+
+
+
+
+/********************* Funktion: loader_initclasses ****************************
+
+       initialisiert alle geladenen aber noch nicht initialisierten Klassen
+
+******************************************************************************/
+
+void loader_initclasses ()
+{
+       classinfo *c;
+       
+       intsDisable();                     /* schani */
+
+       if (makeinitializations) {
+               c = list_first (&linkedclasses);
+               while (c) {
+                       class_init (c);
+                       c = list_next (&linkedclasses, c);
+                       }
+               }
+
+       intsRestore();                      /* schani */
+}
+
+
+
+/******************** Funktion: loader_close **********************************
+
+       gibt alle Resourcen wieder frei
+       
+******************************************************************************/
+
+void loader_close ()
+{
+       classinfo *c;
+
+       while ( (c=list_first(&unloadedclasses)) ) {
+               list_remove (&unloadedclasses,c);
+               class_free (c);
+               }
+       while ( (c=list_first(&unlinkedclasses)) ) {
+               list_remove (&unlinkedclasses,c);
+               class_free (c);
+               }
+       while ( (c=list_first(&linkedclasses)) ) {
+               list_remove (&linkedclasses,c);
+               class_free (c);
+               }
+}
+
diff --git a/src/vm/loader.h b/src/vm/loader.h
new file mode 100644 (file)
index 0000000..190a645
--- /dev/null
@@ -0,0 +1,53 @@
+/******************************* loader.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the prototypes for the class loader.
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1997/11/14
+
+*******************************************************************************/
+
+
+/************************* program switches ***********************************/
+
+extern bool loadverbose;         /* Debug-Meldungen beim Laden ausgeben */
+extern bool linkverbose;
+extern bool initverbose;         /* Meldungen ausgeben, wenn Klasse 
+                                   initialisiert wird */
+extern bool makeinitializations; /* Klassen automatisch initialisieren */
+
+extern bool getloadingtime;
+extern long int loadingtime;     /* CPU-Zeit f"urs Laden der Klassen */
+
+extern list linkedclasses;       /* Liste aller fertig gelinkten Klassen */
+
+
+/************************ prototypes ******************************************/
+
+void loader_init ();
+void loader_close ();
+
+classinfo *loader_load (unicode *topname);
+void loader_initclasses ();
+
+classinfo *class_get (unicode *name);
+voidptr class_getconstant (classinfo *class, u4 pos, u4 ctype);
+u4 class_constanttype (classinfo *class, u4 pos);
+
+fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc);
+methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc);
+
+methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *dest);
+
+bool class_issubclass (classinfo *sub, classinfo *super);
+
+void class_init (classinfo *c);
+
+void class_showmethods (classinfo *c);
+void class_showconstantpool (classinfo *c);
+
diff --git a/src/vm/tables.c b/src/vm/tables.c
new file mode 100644 (file)
index 0000000..fd979fd
--- /dev/null
@@ -0,0 +1,1558 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** tables.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt Supportfunktionen f"ur:
+               - Lesen von JavaClass-Files
+           - unicode-Symbole
+               - den Heap 
+               - zus"atzliche Support-Funktionen
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/03/24
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "global.h"
+#include "tables.h"
+#include "asmpart.h"
+#include "callargs.h"
+
+#include "threads/thread.h"                  /* schani */
+#include "threads/locks.h"
+
+
+bool runverbose = false;
+
+int count_unicode_len = 0;
+
+
+/******************************************************************************
+************************* Der Dateien-Sauger **********************************
+*******************************************************************************
+
+       dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen, 
+       einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
+
+******************************************************************************/
+
+static FILE *classfile = NULL;   /* File-handle der gerade gelesenen Datei */
+static char *classpath = "";     /* Suchpfad f"ur die ClassFiles */
+
+
+
+/************************** Funktion: suck_init ******************************
+
+       Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
+       Klassenfiles
+
+******************************************************************************/
+
+void suck_init (char *cpath)
+{
+       classfile = NULL;
+       classpath = cpath;
+}
+
+
+/************************** Funktion: suck_start ******************************
+
+       "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
+       Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
+       bis eine entsprechende Datei  ( <classname>.class) gefunden wird. 
+       
+******************************************************************************/
+
+bool suck_start (unicode *classname)
+{
+#define MAXFILENAME 1000          /* Maximale Langes des Dateinamens plus Pfad */
+
+       char filename[MAXFILENAME+10];   /* Platz fuer '.class' */
+       u2 filenamelen;
+       char *pathpos;
+       u2 i,c;
+
+
+       pathpos = classpath;
+
+       while (*pathpos) {
+               while ( *pathpos == ':' ) pathpos++;
+               filenamelen=0;
+               while ( (*pathpos) && (*pathpos!=':') ) {
+                   PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+                       
+                       filename[filenamelen++] = *(pathpos++);
+                       }
+
+               filename[filenamelen++] = '/';
+   
+               for (i=0; i < classname -> length; i++) {
+                       PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+                       
+                       c = classname -> text [i];
+                       if (c=='/') c = '/';     /* Slashes im Namen passen zu UNIX */
+                       else {
+                               if ( c<=' ' || c>'z') {
+                                       c = '?';
+                                       }
+                               }
+                       
+                       filename[filenamelen++] = c;    
+                       }
+      
+               strcpy (filename+filenamelen, ".class");
+
+               classfile = fopen(filename, "r");
+               if (classfile) {
+                       return true;
+                       }
+
+               
+               }
+                  
+       sprintf (logtext,"Can not open class file '%s'", filename);
+       error();
+       return false;
+}
+
+
+/************************** Funktion: suck_stop *******************************
+
+       Schlie"st die offene Datei wieder.
+       
+******************************************************************************/
+
+void suck_stop ()
+{
+       u4 rest=0;
+       u1 dummy;
+       
+       while ( fread (&dummy, 1,1, classfile) > 0) rest++;
+       if (rest) {
+               sprintf (logtext,"There are %d access bytes at end of classfile",
+                                (int) rest);
+               dolog();
+               }
+                       
+       fclose (classfile);
+       classfile = NULL;
+}
+      
+
+
+/************************** Lesefunktionen ***********************************
+
+       Lesen von der Datei in verschieden grossen Paketen
+       (8,16,32,64-bit Integer oder Float)
+
+*****************************************************************************/
+
+void suck_nbytes (u1 *buffer, u4 len)
+{
+       if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
+}
+
+
+void skip_nbytes (u4 len)
+{
+       u4 i;
+       for (i=0; i<len; i++) suck_u1 ();
+}
+
+
+u1 suck_u1 ()
+{
+       u1 b;
+       if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+       return b;
+}
+
+s1 suck_s1 ()
+{
+       s1 b;
+       if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+       return b;
+}
+
+
+u2 suck_u2 ()
+{
+       u1 b[2];
+       if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
+       return (b[0]<<8) + b[1];
+}
+
+s2 suck_s2 ()
+{
+       return suck_u2 ();
+}
+
+
+u4 suck_u4 ()
+{
+       u1 b[4];
+       u4 v;
+       if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
+       v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
+       return v;
+}
+
+s4 suck_s4 ()
+{
+       s4 v = suck_u4 ();
+       return v;
+}
+
+u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+       u8 lo,hi;
+       hi = suck_u4();
+       lo = suck_u4();
+       return (hi<<32) + lo;
+#else
+       u8 v;
+       v.high = suck_u4();
+       v.low = suck_u4();
+       return v;
+#endif
+}
+
+s8 suck_s8 ()
+{
+       return suck_u8 ();
+}
+       
+
+float suck_float ()
+{
+       float f;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[4];
+               u2 i;
+               for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+               memcpy ( (u1*) (&f), buffer, 4);
+#else 
+               suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+       PANICIF (sizeof(float) != 4, "Incompatible float-format");
+       
+       return f;
+}
+
+
+double suck_double ()
+{
+       double d;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[8];
+               u2 i;   
+               for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+               memcpy ( (u1*) (&d), buffer, 8);
+#else 
+               suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+       PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+       
+       return d;
+}
+
+
+
+
+/******************************************************************************
+******************** Der Unicode-Symbol-Verwalter *****************************
+*******************************************************************************
+
+       legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
+       das Eintragen neuer Symbole
+       
+******************************************************************************/
+
+
+
+#define UNICODESTART  2187      /* Startgr"osse: moeglichst gross und prim */
+
+static u4 unicodeentries;       /* Anzahl der Eintr"age in der Tabelle */
+static u4 unicodehashsize;      /* Gr"osse der Tabelle */
+static unicode ** unicodehash;  /* Zeiger auf die Tabelle selbst */
+
+
+/*********************** Funktion: unicode_init ******************************
+
+       Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
+       aufgerufen werden)
+       
+*****************************************************************************/
+
+void unicode_init ()
+{
+       u4 i;
+       
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+       unicodeentries = 0;
+       unicodehashsize = UNICODESTART;
+       unicodehash = MNEW (unicode*, unicodehashsize);
+       for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
+}
+
+
+/*********************** Funktion: unicode_close *****************************
+
+       Gibt allen Speicher der Symboltabellen frei.
+       Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist, 
+                  Stringkonstanten (die mit 'unicode_setstringlink' 
+                  Unicode-Symbole gebunden wurden) wieder freizugeben
+       
+*****************************************************************************/
+
+void unicode_close (stringdeleter del)
+{
+       unicode *u;
+       u4 i;
+       
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               while (u) {
+                       unicode *nextu = u->hashlink;
+
+                       if (u->string) del (u->string);
+                       
+                       MFREE (u->text, u2, u->length);
+                       FREE (u, unicode);
+                       u = nextu;
+                       }       
+               }
+       MFREE (unicodehash, unicode*, unicodehashsize);
+}
+
+
+/********************* Funktion: unicode_display ******************************
+       
+       Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
+
+******************************************************************************/
+
+void unicode_display (unicode *u)
+{
+       u2 i,c;
+       for (i=0; i < u->length; i++) {
+               c = u->text[i];
+               if (c>=32 && c<=127) printf ("%c",c);
+                               else printf ("?");
+               }
+       fflush (stdout);
+}
+
+
+/********************* Funktion: unicode_sprint ******************************
+       
+       Schreibt ein unicode-Symbol in einen C-String
+
+******************************************************************************/ 
+
+void unicode_sprint (char *buffer, unicode *u)
+{
+       u2 i;
+       for (i=0; i < u->length; i++) buffer[i] = u->text[i];
+       buffer[i] = '\0';
+}
+
+
+/********************* Funktion: unicode_fprint ******************************
+       
+       Schreibt ein unicode-Symbol auf eine Datei aus
+
+******************************************************************************/ 
+
+void unicode_fprint (FILE *file, unicode *u)
+{
+       u2 i;
+       for (i=0; i < u->length; i++) putc (u->text[i], file);
+} 
+
+
+/****************** interne Funktion: u_hashkey ******************************/
+
+static u4 u_hashkey (u2 *text, u2 length)
+{
+       u4 k = 0;
+       u2 i,sh=0;
+       
+       for (i=0; i<length; i++) {
+               k ^=  ( ((u4) (text[i])) << sh );
+               if (sh<16) sh++;
+                    else  sh=0;
+               }
+               
+       return k;
+}
+
+/*************** interne Funktion: u_reorganizehash **************************/
+
+static void u_reorganizehash ()
+{
+       u4 i;
+       unicode *u;
+
+       u4 newhashsize = unicodehashsize*2;
+       unicode **newhash = MNEW (unicode*, newhashsize);
+
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+       for (i=0; i<newhashsize; i++) newhash[i] = NULL;
+
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               while (u) {
+                       unicode *nextu = u -> hashlink;
+                       u4 slot = (u->key) % newhashsize;
+                                               
+                       u->hashlink = newhash[slot];
+                       newhash[slot] = u;
+
+                       u = nextu;
+                       }
+               }
+       
+       MFREE (unicodehash, unicode*, unicodehashsize);
+       unicodehash = newhash;
+       unicodehashsize = newhashsize;
+}
+
+
+/****************** Funktion: unicode_new_u2 **********************************
+
+       Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+       Funktion als u2-Array "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_u2 (u2 *text, u2 length)
+{
+       u4 key = u_hashkey (text, length);
+       u4 slot = key % unicodehashsize;
+       unicode *u = unicodehash[slot];
+       u2 i;
+
+       while (u) {
+               if (u->key == key) {
+                       if (u->length == length) {
+                               for (i=0; i<length; i++) {
+                                       if (text[i] != u->text[i]) goto nomatch;
+                                       }       
+                                       return u;
+                               }
+                       }
+               nomatch:
+               u = u->hashlink;
+               }
+
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode) + 2 * length;
+#endif
+
+       u = NEW (unicode);
+       u->key = key;
+       u->length = length;
+       u->text = MNEW (u2, length);
+       u->class = NULL;
+       u->string = NULL;
+       u->hashlink = unicodehash[slot];
+       unicodehash[slot] = u;
+       for (i=0; i<length; i++) u->text[i] = text[i];
+
+       unicodeentries++;
+       
+       if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
+       
+       return u;
+}
+
+
+/********************* Funktion: unicode_new_char *****************************
+
+       Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+       Funktion als C-String ( = char* ) "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_char (char *text)
+{
+#define MAXNEWCHAR 500
+       u2 buffer[MAXNEWCHAR];
+       u2 length = 0;
+       u1 c;
+       
+       while ( (c = *text) != '\0' ) {
+               if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
+               buffer[length++] = c;
+               text ++;
+               }
+       return unicode_new_u2 (buffer, length);
+}
+
+
+/********************** Funktion: unicode_setclasslink ************************
+
+       H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
+
+******************************************************************************/
+
+void unicode_setclasslink (unicode *u, classinfo *class)
+{
+       PANICIF (u->class, "Attempt to attach class to already attached symbol");
+       u->class = class;
+}
+
+/********************** Funktion: unicode_getclasslink ************************
+
+       Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
+       Wenn keine solche Klasse existiert, dann wird ein Fehler
+       ausgegeben.
+
+******************************************************************************/
+
+classinfo *unicode_getclasslink (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to get unknown class-reference");
+       return u->class;
+}
+
+
+
+/********************* Funktion: unicode_unlinkclass *************************
+
+       Entfernt den Verweis auf eine Klasse wieder von einem Symbol
+       
+******************************************************************************/
+
+void unicode_unlinkclass (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+       u -> class = NULL;
+}
+
+
+
+/******************* Funktion> unicode_setstringlink *********************
+
+       H"angt einen Verweis auf einen konstanten String an ein 
+       Unicode-Symbol
+       
+*************************************************************************/
+
+void unicode_setstringlink (unicode *u, java_objectheader *str)
+{
+       PANICIF (u->string, "Attempt to attach string to already attached symbol");
+       u->string = str;
+}
+
+
+/********************* Funktion: unicode_unlinkstring *************************
+
+       Entfernt den Verweis auf einen String wieder von einem Symbol
+       
+******************************************************************************/
+
+void unicode_unlinkstring (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+       u -> string = NULL;
+}
+
+
+
+/*********************** Funktion: unicode_show ******************************
+
+       gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
+       (nur f"ur Debug-Zwecke)
+       
+*****************************************************************************/
+
+void unicode_show ()
+{
+       unicode *u;
+       u4 i;
+
+       printf ("UNICODE-HASH: %d slots for %d entries\n", 
+                (int) unicodehashsize, (int) unicodeentries );
+                 
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               if (u) {
+                       printf ("SLOT %d: ", (int) i);
+                       while (u) {
+                               printf ("'");
+                               unicode_display (u);
+                               printf ("' ");
+                               if (u->string) printf ("(string)  ");
+                               u = u->hashlink;
+                               }       
+                       printf ("\n");
+                       }
+               
+               }
+}
+
+
+
+/******************************************************************************
+*********************** Diverse Support-Funktionen ****************************
+******************************************************************************/
+
+
+/******************** Funktion: desc_to_type **********************************
+
+       Findet zu einem gegebenen Typdescriptor den entsprechenden 
+       Java-Grunddatentyp.
+       
+******************************************************************************/
+
+u2 desc_to_type (unicode *descriptor)
+{
+       if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
+       
+       switch (descriptor->text[0]) {
+       case 'B': 
+       case 'C':
+       case 'I':
+       case 'S':  
+       case 'Z':  return TYPE_INT;
+       case 'D':  return TYPE_DOUBLE;
+       case 'F':  return TYPE_FLOAT;
+       case 'J':  return TYPE_LONG;
+       case 'L':
+       case '[':  return TYPE_ADDRESS;
+       }
+                       
+       sprintf (logtext, "Invalid Type-Descriptor: "); 
+       unicode_sprint (logtext+strlen(logtext), descriptor);
+       error (); 
+       return 0;
+}
+
+
+/********************** Funktion: desc_typesize *******************************
+
+       Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
+       der durch den Typdescriptor gegeben ist.
+       
+******************************************************************************/
+
+u2 desc_typesize (unicode *descriptor)
+{
+       switch (desc_to_type(descriptor)) {
+       case TYPE_INT:     return 4;
+       case TYPE_LONG:    return 8;
+       case TYPE_FLOAT:   return 4;
+       case TYPE_DOUBLE:  return 8;
+       case TYPE_ADDRESS: return sizeof(voidptr);
+       default:           return 0;
+       }
+}
+
+
+
+
+
+/******************************************************************************
+********************* Der garbage-collected Heap ******************************
+*******************************************************************************
+
+       verwaltet einen Heap mit automatischer Speicherfreigabe.
+
+       (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
+       collect.doc)
+       
+******************************************************************************/
+
+
+bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
+
+
+#define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
+typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
+
+#if U8_AVAILABLE && SUPPORT_LONG
+#define        bitfieldtype u8
+#define BITFIELDBITS 64
+#else
+#define bitfieldtype u4
+#define BITFIELDBITS 32
+#endif
+
+u4 heapsize;                /* Gr"osse des Heap in Blocks */
+u4 topofheap;               /* Bisherige Obergrenze Heaps */
+heapblock *heap;            /* Speicher f"ur den Heap selbst */
+
+bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
+bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
+bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
+
+u4 heapfillgrade;           /* Menge der Daten im Heap */
+u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
+
+void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
+chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
+
+typedef struct finalizernode {
+       struct finalizernode *next;     
+       u4 objstart;
+       methodinfo *finalizer;
+       } finalizernode;
+       
+finalizernode *livefinalizees;
+finalizernode *deadfinalizees;
+
+
+typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
+       struct memarea *next;
+       } memarea;
+
+typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
+       struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
+       u4 size;
+       } bigmemarea;
+       
+#define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
+memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
+bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
+                                   /* Bitfeld, in dem jeweils ein Bit gesetzt */
+                                   /* ist, wenn eine Liste noch etwas enth"alt */
+
+bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
+
+
+
+
+/**************** Hilfsfunktion: lowest **************************************
+
+liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
+Zahl vom Typ bitfieldtype, das 1 ist.
+Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
+Wert die Funktion l"iefert.
+z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
+
+*****************************************************************************/
+
+static u1 lowesttable[256] = {
+       255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+       
+static int lowest(bitfieldtype i)
+{
+#if BITFIELDBITS==64
+       u8 i1 = i<<32;
+       if (i1) {
+               u8 i11 = i1<<16;
+               if (i11) {
+                       u8 i111 = i11<<8;
+                       if (i111) return lowesttable[i111>>56];
+                       else      return 8+lowesttable[i11>>56];
+                       }
+               else {
+                       u8 i112 = i1<<8;
+                       if (i112) return 16+lowesttable[i112>>56];
+                       else      return 24+lowesttable[i1>>56];
+                       }
+               }
+       else {
+               u8 i12 = i<<16;
+               if (i12) {
+                       u8 i121 = i12<<8;
+                       if (i121) return 32+lowesttable[i121>>56];
+                       else      return 40+lowesttable[i12>>56];
+                       }
+               else {
+                       u8 i122 = i<<8;
+                       if (i122) return 48+lowesttable[i122>>56];
+                       else      return 56+lowesttable[i>>56];
+                       }
+               }
+#else
+       u4 i1 = i<<16;
+       if (i1) {
+               u4 i11 = i1<<8;
+               if (i11) return lowesttable[i11>>24];
+               else     return 8+lowesttable[i1>>24];
+               }
+       else {
+               u4 i12 = i<<8;
+               if (i12) return 16+lowesttable[i12>>24];
+               else     return 24+lowesttable[i>>24];
+               }
+#endif
+}
+
+
+/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
+
+static void setbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] |= 
+         ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] &= 
+          ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+          ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
+}
+
+static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+           ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
+}
+
+
+/***************** Funktion: clearbitfield ************************************
+       
+       l"oscht ein ganzes Bitfeld
+       
+******************************************************************************/
+
+static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
+{ 
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] = 0;
+}
+
+/************** Funktion: maskfieldwithfield **********************************
+       
+       Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
+       wird mit dem Ergebnis "uberschrieben 
+       
+******************************************************************************/
+       
+static void maskfieldwithfield (bitfieldtype* bitfield, 
+                                bitfieldtype *maskfield, u4 fieldsize)
+{
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
+}
+
+
+/************** Funktion: findnextsetbit **************************************
+
+       Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
+       und liefert die Nummer dieses Bits.
+       Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
+       ist, dann wird fieldsize zur"uckgeliefte.
+
+******************************************************************************/
+
+static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern = bitfield[bitnumber/BITFIELDBITS];
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+/************ Funktion: findnextcombination_set_unset *************************
+
+       funktioniert wie findnextsetbit, allerdings sucht diese Funktion
+       nach einer Stelle, an der gleichzeitig ein Bit im ersten
+       Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
+       Bit nicht gesetzt ist.
+
+******************************************************************************/
+
+static u4 findnextcombination_set_unset 
+       (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern =     bitfield1[bitnumber/BITFIELDBITS] 
+                         & (~bitfield2[bitnumber/BITFIELDBITS]);
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+
+/************** Funktion: memlist_init ****************************************
+
+       initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
+       mit memlist_addrange).
+
+******************************************************************************/
+
+static void memlist_init ()
+{
+       u4 i;
+       for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
+       clearbitfield (memlistbits, DIFFERENTSIZES);
+       bigmemlist = NULL;
+}
+
+
+/************** Funktion: memlist_addrange ************************************
+
+       f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
+       hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
+       Verkettungszeiger hineingeschrieben).
+
+******************************************************************************/
+
+static void memlist_addrange (u4 freestart, u4 freesize)
+{
+       if (freesize>=DIFFERENTSIZES) {
+               bigmemarea *m = (bigmemarea*) (heap+freestart);
+               m -> next = bigmemlist;
+               m -> size = freesize;
+               bigmemlist = m;
+               }
+       else {
+               if (freesize*BLOCKSIZE>=sizeof(memarea)) {
+                       memarea *m = (memarea*) (heap+freestart);
+                       m -> next = memlist[freesize];
+                       memlist[freesize] = m;
+                       setbit (memlistbits, freesize);
+                       }
+               }
+}
+
+
+/************** Funktion: memlist_getsuitable *********************************
+
+       sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
+       genau die gew"unschte L"ange hat.
+       Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
+       (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
+       Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
+       
+       Return (in Referenzparametern): 
+               *freestart: Anfang des freien Speichers
+               *freelength: L"ange dieses Speicherbereiches
+
+       Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
+       wird in '*freelength' 0 hineingeschrieben.
+       
+******************************************************************************/                
+
+static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
+{
+       bigmemarea *m;
+       bigmemarea *prevm = NULL;
+       
+       if (length<DIFFERENTSIZES) {
+               u4 firstfreelength;
+
+               if (memlist[length]) {
+                       firstfreelength = length;
+                       }
+               else {
+                       firstfreelength = findnextsetbit 
+                               (memlistbits, DIFFERENTSIZES, length+3); 
+                               /* wenn kein passender Block da ist, dann gleich nach */
+                               /* einem etwas gr"osseren suchen, damit keine kleinen */
+                               /* St"uckchen "ubrigbleiben */
+                       }
+                       
+               if (firstfreelength<DIFFERENTSIZES) {
+                       memarea *m = memlist[firstfreelength];
+                       memlist[firstfreelength] = m->next;             
+                       if (!m->next) clearbit (memlistbits, firstfreelength);
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = firstfreelength;
+                       return;
+                       }
+               }
+
+       m = bigmemlist;
+       while (m) {
+               if (m->size >= length) {
+                       if (prevm) prevm->next = m->next;                                       
+                               else   bigmemlist = m->next;
+                       
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = m->size;
+                       return ;                        
+                       }
+
+               prevm = m;
+               m = m->next;
+               }
+       
+       *freelength=0;
+}
+
+
+
+
+
+/******************* Funktion: mark *******************************************
+
+       Markiert ein m"oglicherweise g"ultiges Objekt.
+       Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
+       am Heap zeigt, dann wird eben gar nichts markiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend);
+
+static void mark (heapblock *obj)
+{
+       u4 blocknum,objectend;
+
+       if ((long) obj & (BLOCKSIZE-1)) return;
+       
+       if (obj<heap) return;
+       if (obj>=(heap+topofheap) ) return;
+
+       blocknum = obj-heap;
+       if ( isbitclear(startbits, blocknum) ) return;
+       if ( isbitset(markbits, blocknum) ) return;
+
+       setbit (markbits, blocknum);
+       
+       if ( isbitclear(referencebits, blocknum) ) return;
+
+       objectend = findnextsetbit (startbits, topofheap, blocknum+1);
+       markreferences ((void**)obj, (void**) (heap+objectend) );
+}
+
+
+/******************** Funktion: markreferences ********************************
+
+       Geht einen Speicherbereich durch, und markiert alle Objekte, auf
+       die von diesem Bereich aus irgendeine Referenz existiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend)
+{
+       void **ptr;
+       
+       for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
+}
+
+
+/******************* Funktion: markstack **************************************
+
+        Marks all objects that are referenced by the (C-)stacks of
+        all live threads.
+
+       (The stack-bottom is to be specified in the call to heap_init).
+
+******************************************************************************/
+
+static void markstack ()                   /* schani */
+{
+       void *dummy;
+       void **top_of_stack = &dummy;
+
+#ifdef USE_THREADS
+       thread *aThread;
+
+       for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
+               mark((heapblock*)aThread);
+               if (aThread == currentThread) {
+                       if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
+                       else    
+                               markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
+                       }
+               else {
+                       if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd,
+                                               (void**)CONTEXT(aThread).usedStackTop + 16);
+                       else    
+                               markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
+                                               (void**)CONTEXT(aThread).stackEnd);
+                       }
+               }
+
+       markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+#else
+       if (top_of_stack > bottom_of_stack)
+               markreferences(bottom_of_stack, top_of_stack);
+       else
+               markreferences(top_of_stack, bottom_of_stack);
+#endif
+}
+
+
+
+/**************** Funktion: searchlivefinalizees *****************************
+
+       geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
+       (livefinalizees), und tr"agt alle nicht mehr markierten in die
+       Liste deadfinalizess ein (allerdings werden sie vorher noch als
+       erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
+       
+*****************************************************************************/ 
+
+static void searchlivefinalizees ()
+{
+       finalizernode *fn = livefinalizees;
+       finalizernode *lastlive = NULL;
+               
+       while (fn) {
+       
+               /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
+               if (isbitclear (markbits, fn->objstart)) {
+                       finalizernode *nextfn = fn->next;
+
+                       mark (heap + fn->objstart); 
+
+                       if (lastlive) lastlive -> next = nextfn;
+                                      else livefinalizees = nextfn;
+
+                       fn -> next = deadfinalizees;
+                       deadfinalizees = fn;
+                       
+                       fn = nextfn;
+                       }
+               else {  
+                       lastlive = fn;
+                       fn = fn->next;
+                       }
+               }
+}
+
+
+
+/********************** Funktion: finalizedead *******************************
+
+       ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
+       Liste auf.
+       Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
+       (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
+       globalen Variablen in lokale Variblen kopiert werden 
+       (Reentrant-F"ahigkeit!!!)
+        
+******************************************************************************/
+
+static void finalizedead()
+{
+       finalizernode *fn = deadfinalizees;
+       deadfinalizees = NULL;
+       
+       while (fn) {
+               finalizernode *nextfn = fn->next;
+               
+               asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
+               FREE (fn, finalizernode);
+               
+               fn = nextfn;
+               }
+
+}
+
+
+
+/****************** Funktion: heap_docollect **********************************
+       
+       F"uhrt eine vollst"andige Garbage Collection durch
+       
+******************************************************************************/
+
+static void heap_docollect ()
+{
+       u4 freestart,freeend;
+       void **p;
+       bitfieldtype *dummy;
+       u4 heapfreemem;
+       u4 oldfillgrade;
+
+
+       if (runverbose) {
+               fprintf(stderr, "doing garbage collection\n");
+               }
+               /* alle Markierungsbits l"oschen */
+       clearbitfield (markbits, topofheap);
+
+               /* Alle vom Stack referenzierten Objekte markieren */
+       asm_dumpregistersandcall (markstack);
+
+               /* Alle von globalen Variablen erreichbaren Objekte markieren */
+       p = chain_first (allglobalreferences);
+       while (p) {
+               mark (*p);
+               p = chain_next (allglobalreferences);   
+               }
+
+               /* alle Objekte durchsehen, die eine finalizer-Methode haben */
+       searchlivefinalizees();
+
+               /* alle Reference-Bits l"oschen, deren Objekte nicht */
+               /* mehr erreichbar sind */
+       maskfieldwithfield (referencebits, markbits, topofheap);
+
+
+               /* Freispeicherliste initialisieren */
+       memlist_init ();
+       
+       
+               /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
+
+       heapfreemem = 0;
+       freeend=0;
+       for (;;) {
+                       /* Anfang des n"achsten freien Bereiches suchen */
+               freestart = findnextcombination_set_unset 
+                       (startbits, markbits, topofheap, freeend);
+
+                       /* Wenn es keinen freien Bereich mehr gibt -> fertig */
+               if (freestart>=topofheap) goto freememfinished;
+
+                       /* Anfang des freien Bereiches markieren */
+               setbit (markbits, freestart);
+
+                       /* Ende des freien Bereiches suchen */          
+               freeend = findnextsetbit (markbits, topofheap, freestart+1);
+
+                       /* Freien Bereich in Freispeicherliste einh"angen */
+               memlist_addrange (freestart, freeend-freestart);
+
+                       /* Menge des freien Speichers mitnotieren */
+               heapfreemem += (freeend-freestart);
+               }
+
+       freememfinished:
+
+               /* Die Rollen von markbits und startbits vertauschen */ 
+       dummy = markbits;
+       markbits = startbits;
+       startbits = dummy;
+
+
+               /* Threashold-Wert f"ur n"achstes Collect */
+       oldfillgrade = heapfillgrade;
+       heapfillgrade = topofheap - heapfreemem;
+       collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
+
+               /* Eventuell eine Meldung ausgeben */
+       if (collectverbose) {
+               sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
+                 (int) (oldfillgrade * BLOCKSIZE), 
+                 (int) (heapfillgrade * BLOCKSIZE) );
+               dolog ();
+               }
+
+
+               
+               /* alle gerade unerreichbar gewordenen Objekte mit 
+                  finalize-Methoden jetzt finalisieren.
+                  Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
+       finalizedead ();
+       
+}
+
+/************************* Function: gc_init **********************************
+
+        Initializes the garbage collection thread mechanism.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+iMux gcStartMutex;
+iMux gcThreadMutex;
+iCv gcConditionStart;
+iCv gcConditionDone;
+
+void
+gc_init (void)
+{
+    gcStartMutex.holder = 0;
+    gcStartMutex.count = 0;
+    gcStartMutex.muxWaiters = 0;
+
+    gcThreadMutex.holder = 0;
+    gcThreadMutex.count = 0;
+    gcThreadMutex.muxWaiters = 0;
+
+    gcConditionStart.cvWaiters = 0;
+    gcConditionStart.mux = 0;
+
+    gcConditionDone.cvWaiters = 0;
+    gcConditionDone.mux = 0;
+}    
+#else
+void
+gc_init (void)
+{
+}
+#endif
+
+/************************* Function: gc_thread ********************************
+
+        In an endless loop waits for a condition to be posted, then
+       garbage collects the heap.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+void
+gc_thread (void)
+{
+    intsRestore();           /* all threads start with interrupts disabled */
+
+       assert(blockInts == 0);
+
+    lock_mutex(&gcThreadMutex);
+
+    for (;;)
+    {
+               wait_cond(&gcThreadMutex, &gcConditionStart, 0);
+
+               intsDisable();
+               heap_docollect();
+               intsRestore();
+
+               signal_cond(&gcConditionDone);
+    }
+}
+#endif
+
+void
+gc_call (void)
+{
+#ifdef USE_THREADS
+    lock_mutex(&gcThreadMutex);
+
+    signal_cond(&gcConditionStart);
+    wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+
+    unlock_mutex(&gcThreadMutex);
+#else
+    heap_docollect();
+#endif
+}
+
+
+/************************* Funktion: heap_init ********************************
+
+       Initialisiert den Garbage Collector.
+       Parameter: 
+               heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
+               heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
+                                  GC durchgef"uhrt werden soll.
+               stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
+                              Referenzen auf Objekte stehen k"onnen.                  
+                                          
+******************************************************************************/
+
+void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
+{
+
+#ifdef TRACECALLARGS
+
+       heapsize = ALIGN (heapbytesize, getpagesize());
+       heapsize = heapsize/BLOCKSIZE;
+       heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
+              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
+       if (heap != (void *) 0x10000000) {
+               perror("mmap");
+               printf("address = %p\n", heap);
+               panic("mmap failed\n");
+               }
+
+#else
+
+       heapsize = ALIGN (heapbytesize, 1024);
+       heapsize = heapsize/BLOCKSIZE;
+       heap = MNEW (heapblock, heapsize);
+
+#endif
+
+       topofheap = 0;
+       startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       clearbitfield (startbits, heapsize);
+       clearbitfield (markbits, heapsize);
+       clearbitfield (referencebits, heapsize);
+
+       heapfillgrade = 0;
+       collectthreashold = heapbytestartsize/BLOCKSIZE;
+       allglobalreferences = chain_new ();
+       bottom_of_stack = stackbottom;
+
+       livefinalizees = NULL;
+       deadfinalizees = NULL;
+}
+
+
+/****************** Funktion: heap_close **************************************
+
+       Gibt allen ben"otigten Speicher frei
+
+******************************************************************************/
+
+void heap_close ()
+{
+#ifndef TRACECALLARGS
+       MFREE (heap, heapblock, heapsize); */
+#endif
+       MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
+       chain_free (allglobalreferences);
+
+       while (livefinalizees) {
+               finalizernode *n = livefinalizees->next;
+               FREE (livefinalizees, finalizernode);
+               livefinalizees = n;
+               }
+}
+
+
+/***************** Funktion: heap_addreference ********************************
+
+       Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
+       auf Objekte gespeichert sein kann.
+
+******************************************************************************/
+
+void heap_addreference (void **reflocation)
+{
+       intsDisable();                     /* schani */
+
+       chain_addlast (allglobalreferences, reflocation);
+
+       intsRestore();                    /* schani */
+}
+
+
+
+/***************** Funktion: heap_allocate ************************************
+
+       Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
+       (in Byte angegeben) haben muss.
+       Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
+       Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
+       Zus"atzlich wird durch den Parameter 'references' angegeben, ob
+       in das angelegte Objekt Referenzen auf andere Objekte eingetragen
+       werden k"onnten. 
+       (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
+       Im Zweifelsfalle immer references=true verwenden.
+
+******************************************************************************/
+
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
+{
+       u4 freestart,freelength;
+       u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+       
+       intsDisable();                        /* schani */
+
+       memlist_getsuitable (&freestart, &freelength, length);
+
+onemoretry:
+       if (!freelength) {
+               if (    (topofheap+length > collectthreashold) 
+                    || (topofheap+length > heapsize) ) {
+
+                       intsRestore();
+                       gc_call();
+                       intsDisable();
+                       
+                       memlist_getsuitable (&freestart, &freelength, length);
+                       if (freelength) goto onemoretry;
+                       }
+               
+               if (topofheap+length > heapsize) {
+                       sprintf (logtext, "Heap-Allocation failed for %d bytes", 
+                           (int) bytelength);
+                       dolog();
+                       intsRestore();            /* schani */
+                       return NULL;
+                       }
+                       
+               freestart = topofheap;
+               freelength = length;
+               setbit (startbits, topofheap);
+               topofheap += length;
+               }
+       else {
+               if (freelength>length) {
+                       setbit (startbits, freestart+length);
+                       memlist_addrange (freestart+length, freelength-length);
+                       }
+               }
+               
+       if (references) setbit (referencebits, freestart);
+
+       heapfillgrade += length;
+
+       if (finalizer) {
+               finalizernode *n = NEW(finalizernode);
+               n -> next = livefinalizees;
+               n -> objstart = freestart;
+               n -> finalizer = finalizer;
+               livefinalizees = n;
+               }
+       
+       intsRestore();                   /* schani */
+
+       if (runverbose) {
+               sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
+               dolog ();
+               }
+
+       return (void*) (heap + freestart);
+}
+
+
+
+
diff --git a/src/vm/tables.h b/src/vm/tables.h
new file mode 100644 (file)
index 0000000..80f7893
--- /dev/null
@@ -0,0 +1,63 @@
+/****************************** tables.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/20
+
+*******************************************************************************/
+
+extern bool collectverbose;
+
+
+#define CLASS(name)     (unicode_getclasslink(unicode_new_char(name)))
+
+typedef void (*stringdeleter) ( java_objectheader *string );
+
+
+void suck_init (char *classpath);
+bool suck_start (unicode *name);
+void suck_stop ();
+void suck_nbytes (u1 *buffer, u4 len);
+void skip_nbytes (u4 len);
+u1 suck_u1 ();
+s1 suck_s1 ();
+u2 suck_u2 ();
+s2 suck_s2 ();
+u4 suck_u4 ();
+s4 suck_s4 ();
+u8 suck_u8 ();
+s8 suck_s8 ();
+float suck_float ();
+double suck_double ();
+
+
+void unicode_init ();
+void unicode_close (stringdeleter del);
+void unicode_display (unicode *u);
+void unicode_sprint (char *buffer, unicode *u);
+void unicode_fprint (FILE *file, unicode *u);
+unicode *unicode_new_u2 (u2 *text, u2 length);
+unicode *unicode_new_char (char *text);
+void unicode_setclasslink (unicode *u, classinfo *class);
+classinfo *unicode_getclasslink (unicode *u);
+void unicode_unlinkclass (unicode *u);
+void unicode_setstringlink (unicode *u, java_objectheader *str);
+void unicode_unlinkstring (unicode *u);
+void unicode_show ();
+
+u2 desc_to_type (unicode *descriptor);
+u2 desc_typesize (unicode *descriptor);
+
+
+void heap_init (u4 size, u4 startsize, void **stackbottom);
+void heap_close ();
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer);
+void heap_addreference (void **reflocation);
+
+void gc_init (void);
+void gc_thread (void);
+void gc_call (void);
diff --git a/tables.c b/tables.c
new file mode 100644 (file)
index 0000000..fd979fd
--- /dev/null
+++ b/tables.c
@@ -0,0 +1,1558 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** tables.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt Supportfunktionen f"ur:
+               - Lesen von JavaClass-Files
+           - unicode-Symbole
+               - den Heap 
+               - zus"atzliche Support-Funktionen
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/03/24
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "global.h"
+#include "tables.h"
+#include "asmpart.h"
+#include "callargs.h"
+
+#include "threads/thread.h"                  /* schani */
+#include "threads/locks.h"
+
+
+bool runverbose = false;
+
+int count_unicode_len = 0;
+
+
+/******************************************************************************
+************************* Der Dateien-Sauger **********************************
+*******************************************************************************
+
+       dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen, 
+       einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
+
+******************************************************************************/
+
+static FILE *classfile = NULL;   /* File-handle der gerade gelesenen Datei */
+static char *classpath = "";     /* Suchpfad f"ur die ClassFiles */
+
+
+
+/************************** Funktion: suck_init ******************************
+
+       Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
+       Klassenfiles
+
+******************************************************************************/
+
+void suck_init (char *cpath)
+{
+       classfile = NULL;
+       classpath = cpath;
+}
+
+
+/************************** Funktion: suck_start ******************************
+
+       "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
+       Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
+       bis eine entsprechende Datei  ( <classname>.class) gefunden wird. 
+       
+******************************************************************************/
+
+bool suck_start (unicode *classname)
+{
+#define MAXFILENAME 1000          /* Maximale Langes des Dateinamens plus Pfad */
+
+       char filename[MAXFILENAME+10];   /* Platz fuer '.class' */
+       u2 filenamelen;
+       char *pathpos;
+       u2 i,c;
+
+
+       pathpos = classpath;
+
+       while (*pathpos) {
+               while ( *pathpos == ':' ) pathpos++;
+               filenamelen=0;
+               while ( (*pathpos) && (*pathpos!=':') ) {
+                   PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+                       
+                       filename[filenamelen++] = *(pathpos++);
+                       }
+
+               filename[filenamelen++] = '/';
+   
+               for (i=0; i < classname -> length; i++) {
+                       PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+                       
+                       c = classname -> text [i];
+                       if (c=='/') c = '/';     /* Slashes im Namen passen zu UNIX */
+                       else {
+                               if ( c<=' ' || c>'z') {
+                                       c = '?';
+                                       }
+                               }
+                       
+                       filename[filenamelen++] = c;    
+                       }
+      
+               strcpy (filename+filenamelen, ".class");
+
+               classfile = fopen(filename, "r");
+               if (classfile) {
+                       return true;
+                       }
+
+               
+               }
+                  
+       sprintf (logtext,"Can not open class file '%s'", filename);
+       error();
+       return false;
+}
+
+
+/************************** Funktion: suck_stop *******************************
+
+       Schlie"st die offene Datei wieder.
+       
+******************************************************************************/
+
+void suck_stop ()
+{
+       u4 rest=0;
+       u1 dummy;
+       
+       while ( fread (&dummy, 1,1, classfile) > 0) rest++;
+       if (rest) {
+               sprintf (logtext,"There are %d access bytes at end of classfile",
+                                (int) rest);
+               dolog();
+               }
+                       
+       fclose (classfile);
+       classfile = NULL;
+}
+      
+
+
+/************************** Lesefunktionen ***********************************
+
+       Lesen von der Datei in verschieden grossen Paketen
+       (8,16,32,64-bit Integer oder Float)
+
+*****************************************************************************/
+
+void suck_nbytes (u1 *buffer, u4 len)
+{
+       if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
+}
+
+
+void skip_nbytes (u4 len)
+{
+       u4 i;
+       for (i=0; i<len; i++) suck_u1 ();
+}
+
+
+u1 suck_u1 ()
+{
+       u1 b;
+       if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+       return b;
+}
+
+s1 suck_s1 ()
+{
+       s1 b;
+       if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
+       return b;
+}
+
+
+u2 suck_u2 ()
+{
+       u1 b[2];
+       if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
+       return (b[0]<<8) + b[1];
+}
+
+s2 suck_s2 ()
+{
+       return suck_u2 ();
+}
+
+
+u4 suck_u4 ()
+{
+       u1 b[4];
+       u4 v;
+       if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
+       v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
+       return v;
+}
+
+s4 suck_s4 ()
+{
+       s4 v = suck_u4 ();
+       return v;
+}
+
+u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+       u8 lo,hi;
+       hi = suck_u4();
+       lo = suck_u4();
+       return (hi<<32) + lo;
+#else
+       u8 v;
+       v.high = suck_u4();
+       v.low = suck_u4();
+       return v;
+#endif
+}
+
+s8 suck_s8 ()
+{
+       return suck_u8 ();
+}
+       
+
+float suck_float ()
+{
+       float f;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[4];
+               u2 i;
+               for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+               memcpy ( (u1*) (&f), buffer, 4);
+#else 
+               suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+       PANICIF (sizeof(float) != 4, "Incompatible float-format");
+       
+       return f;
+}
+
+
+double suck_double ()
+{
+       double d;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[8];
+               u2 i;   
+               for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+               memcpy ( (u1*) (&d), buffer, 8);
+#else 
+               suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+       PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+       
+       return d;
+}
+
+
+
+
+/******************************************************************************
+******************** Der Unicode-Symbol-Verwalter *****************************
+*******************************************************************************
+
+       legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
+       das Eintragen neuer Symbole
+       
+******************************************************************************/
+
+
+
+#define UNICODESTART  2187      /* Startgr"osse: moeglichst gross und prim */
+
+static u4 unicodeentries;       /* Anzahl der Eintr"age in der Tabelle */
+static u4 unicodehashsize;      /* Gr"osse der Tabelle */
+static unicode ** unicodehash;  /* Zeiger auf die Tabelle selbst */
+
+
+/*********************** Funktion: unicode_init ******************************
+
+       Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
+       aufgerufen werden)
+       
+*****************************************************************************/
+
+void unicode_init ()
+{
+       u4 i;
+       
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+       unicodeentries = 0;
+       unicodehashsize = UNICODESTART;
+       unicodehash = MNEW (unicode*, unicodehashsize);
+       for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
+}
+
+
+/*********************** Funktion: unicode_close *****************************
+
+       Gibt allen Speicher der Symboltabellen frei.
+       Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist, 
+                  Stringkonstanten (die mit 'unicode_setstringlink' 
+                  Unicode-Symbole gebunden wurden) wieder freizugeben
+       
+*****************************************************************************/
+
+void unicode_close (stringdeleter del)
+{
+       unicode *u;
+       u4 i;
+       
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               while (u) {
+                       unicode *nextu = u->hashlink;
+
+                       if (u->string) del (u->string);
+                       
+                       MFREE (u->text, u2, u->length);
+                       FREE (u, unicode);
+                       u = nextu;
+                       }       
+               }
+       MFREE (unicodehash, unicode*, unicodehashsize);
+}
+
+
+/********************* Funktion: unicode_display ******************************
+       
+       Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
+
+******************************************************************************/
+
+void unicode_display (unicode *u)
+{
+       u2 i,c;
+       for (i=0; i < u->length; i++) {
+               c = u->text[i];
+               if (c>=32 && c<=127) printf ("%c",c);
+                               else printf ("?");
+               }
+       fflush (stdout);
+}
+
+
+/********************* Funktion: unicode_sprint ******************************
+       
+       Schreibt ein unicode-Symbol in einen C-String
+
+******************************************************************************/ 
+
+void unicode_sprint (char *buffer, unicode *u)
+{
+       u2 i;
+       for (i=0; i < u->length; i++) buffer[i] = u->text[i];
+       buffer[i] = '\0';
+}
+
+
+/********************* Funktion: unicode_fprint ******************************
+       
+       Schreibt ein unicode-Symbol auf eine Datei aus
+
+******************************************************************************/ 
+
+void unicode_fprint (FILE *file, unicode *u)
+{
+       u2 i;
+       for (i=0; i < u->length; i++) putc (u->text[i], file);
+} 
+
+
+/****************** interne Funktion: u_hashkey ******************************/
+
+static u4 u_hashkey (u2 *text, u2 length)
+{
+       u4 k = 0;
+       u2 i,sh=0;
+       
+       for (i=0; i<length; i++) {
+               k ^=  ( ((u4) (text[i])) << sh );
+               if (sh<16) sh++;
+                    else  sh=0;
+               }
+               
+       return k;
+}
+
+/*************** interne Funktion: u_reorganizehash **************************/
+
+static void u_reorganizehash ()
+{
+       u4 i;
+       unicode *u;
+
+       u4 newhashsize = unicodehashsize*2;
+       unicode **newhash = MNEW (unicode*, newhashsize);
+
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode*) * unicodehashsize;
+#endif
+
+       for (i=0; i<newhashsize; i++) newhash[i] = NULL;
+
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               while (u) {
+                       unicode *nextu = u -> hashlink;
+                       u4 slot = (u->key) % newhashsize;
+                                               
+                       u->hashlink = newhash[slot];
+                       newhash[slot] = u;
+
+                       u = nextu;
+                       }
+               }
+       
+       MFREE (unicodehash, unicode*, unicodehashsize);
+       unicodehash = newhash;
+       unicodehashsize = newhashsize;
+}
+
+
+/****************** Funktion: unicode_new_u2 **********************************
+
+       Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+       Funktion als u2-Array "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_u2 (u2 *text, u2 length)
+{
+       u4 key = u_hashkey (text, length);
+       u4 slot = key % unicodehashsize;
+       unicode *u = unicodehash[slot];
+       u2 i;
+
+       while (u) {
+               if (u->key == key) {
+                       if (u->length == length) {
+                               for (i=0; i<length; i++) {
+                                       if (text[i] != u->text[i]) goto nomatch;
+                                       }       
+                                       return u;
+                               }
+                       }
+               nomatch:
+               u = u->hashlink;
+               }
+
+#ifdef STATISTICS
+       count_unicode_len += sizeof(unicode) + 2 * length;
+#endif
+
+       u = NEW (unicode);
+       u->key = key;
+       u->length = length;
+       u->text = MNEW (u2, length);
+       u->class = NULL;
+       u->string = NULL;
+       u->hashlink = unicodehash[slot];
+       unicodehash[slot] = u;
+       for (i=0; i<length; i++) u->text[i] = text[i];
+
+       unicodeentries++;
+       
+       if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
+       
+       return u;
+}
+
+
+/********************* Funktion: unicode_new_char *****************************
+
+       Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
+       Funktion als C-String ( = char* ) "ubergeben
+
+******************************************************************************/
+
+unicode *unicode_new_char (char *text)
+{
+#define MAXNEWCHAR 500
+       u2 buffer[MAXNEWCHAR];
+       u2 length = 0;
+       u1 c;
+       
+       while ( (c = *text) != '\0' ) {
+               if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
+               buffer[length++] = c;
+               text ++;
+               }
+       return unicode_new_u2 (buffer, length);
+}
+
+
+/********************** Funktion: unicode_setclasslink ************************
+
+       H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
+
+******************************************************************************/
+
+void unicode_setclasslink (unicode *u, classinfo *class)
+{
+       PANICIF (u->class, "Attempt to attach class to already attached symbol");
+       u->class = class;
+}
+
+/********************** Funktion: unicode_getclasslink ************************
+
+       Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
+       Wenn keine solche Klasse existiert, dann wird ein Fehler
+       ausgegeben.
+
+******************************************************************************/
+
+classinfo *unicode_getclasslink (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to get unknown class-reference");
+       return u->class;
+}
+
+
+
+/********************* Funktion: unicode_unlinkclass *************************
+
+       Entfernt den Verweis auf eine Klasse wieder von einem Symbol
+       
+******************************************************************************/
+
+void unicode_unlinkclass (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+       u -> class = NULL;
+}
+
+
+
+/******************* Funktion> unicode_setstringlink *********************
+
+       H"angt einen Verweis auf einen konstanten String an ein 
+       Unicode-Symbol
+       
+*************************************************************************/
+
+void unicode_setstringlink (unicode *u, java_objectheader *str)
+{
+       PANICIF (u->string, "Attempt to attach string to already attached symbol");
+       u->string = str;
+}
+
+
+/********************* Funktion: unicode_unlinkstring *************************
+
+       Entfernt den Verweis auf einen String wieder von einem Symbol
+       
+******************************************************************************/
+
+void unicode_unlinkstring (unicode *u)
+{
+       PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
+       u -> string = NULL;
+}
+
+
+
+/*********************** Funktion: unicode_show ******************************
+
+       gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
+       (nur f"ur Debug-Zwecke)
+       
+*****************************************************************************/
+
+void unicode_show ()
+{
+       unicode *u;
+       u4 i;
+
+       printf ("UNICODE-HASH: %d slots for %d entries\n", 
+                (int) unicodehashsize, (int) unicodeentries );
+                 
+       for (i=0; i<unicodehashsize; i++) {
+               u = unicodehash[i];
+               if (u) {
+                       printf ("SLOT %d: ", (int) i);
+                       while (u) {
+                               printf ("'");
+                               unicode_display (u);
+                               printf ("' ");
+                               if (u->string) printf ("(string)  ");
+                               u = u->hashlink;
+                               }       
+                       printf ("\n");
+                       }
+               
+               }
+}
+
+
+
+/******************************************************************************
+*********************** Diverse Support-Funktionen ****************************
+******************************************************************************/
+
+
+/******************** Funktion: desc_to_type **********************************
+
+       Findet zu einem gegebenen Typdescriptor den entsprechenden 
+       Java-Grunddatentyp.
+       
+******************************************************************************/
+
+u2 desc_to_type (unicode *descriptor)
+{
+       if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
+       
+       switch (descriptor->text[0]) {
+       case 'B': 
+       case 'C':
+       case 'I':
+       case 'S':  
+       case 'Z':  return TYPE_INT;
+       case 'D':  return TYPE_DOUBLE;
+       case 'F':  return TYPE_FLOAT;
+       case 'J':  return TYPE_LONG;
+       case 'L':
+       case '[':  return TYPE_ADDRESS;
+       }
+                       
+       sprintf (logtext, "Invalid Type-Descriptor: "); 
+       unicode_sprint (logtext+strlen(logtext), descriptor);
+       error (); 
+       return 0;
+}
+
+
+/********************** Funktion: desc_typesize *******************************
+
+       Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
+       der durch den Typdescriptor gegeben ist.
+       
+******************************************************************************/
+
+u2 desc_typesize (unicode *descriptor)
+{
+       switch (desc_to_type(descriptor)) {
+       case TYPE_INT:     return 4;
+       case TYPE_LONG:    return 8;
+       case TYPE_FLOAT:   return 4;
+       case TYPE_DOUBLE:  return 8;
+       case TYPE_ADDRESS: return sizeof(voidptr);
+       default:           return 0;
+       }
+}
+
+
+
+
+
+/******************************************************************************
+********************* Der garbage-collected Heap ******************************
+*******************************************************************************
+
+       verwaltet einen Heap mit automatischer Speicherfreigabe.
+
+       (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
+       collect.doc)
+       
+******************************************************************************/
+
+
+bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
+
+
+#define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
+typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
+
+#if U8_AVAILABLE && SUPPORT_LONG
+#define        bitfieldtype u8
+#define BITFIELDBITS 64
+#else
+#define bitfieldtype u4
+#define BITFIELDBITS 32
+#endif
+
+u4 heapsize;                /* Gr"osse des Heap in Blocks */
+u4 topofheap;               /* Bisherige Obergrenze Heaps */
+heapblock *heap;            /* Speicher f"ur den Heap selbst */
+
+bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
+bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
+bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
+
+u4 heapfillgrade;           /* Menge der Daten im Heap */
+u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
+
+void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
+chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
+
+typedef struct finalizernode {
+       struct finalizernode *next;     
+       u4 objstart;
+       methodinfo *finalizer;
+       } finalizernode;
+       
+finalizernode *livefinalizees;
+finalizernode *deadfinalizees;
+
+
+typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
+       struct memarea *next;
+       } memarea;
+
+typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
+       struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
+       u4 size;
+       } bigmemarea;
+       
+#define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
+memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
+bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
+                                   /* Bitfeld, in dem jeweils ein Bit gesetzt */
+                                   /* ist, wenn eine Liste noch etwas enth"alt */
+
+bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
+
+
+
+
+/**************** Hilfsfunktion: lowest **************************************
+
+liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
+Zahl vom Typ bitfieldtype, das 1 ist.
+Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
+Wert die Funktion l"iefert.
+z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
+
+*****************************************************************************/
+
+static u1 lowesttable[256] = {
+       255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+       
+static int lowest(bitfieldtype i)
+{
+#if BITFIELDBITS==64
+       u8 i1 = i<<32;
+       if (i1) {
+               u8 i11 = i1<<16;
+               if (i11) {
+                       u8 i111 = i11<<8;
+                       if (i111) return lowesttable[i111>>56];
+                       else      return 8+lowesttable[i11>>56];
+                       }
+               else {
+                       u8 i112 = i1<<8;
+                       if (i112) return 16+lowesttable[i112>>56];
+                       else      return 24+lowesttable[i1>>56];
+                       }
+               }
+       else {
+               u8 i12 = i<<16;
+               if (i12) {
+                       u8 i121 = i12<<8;
+                       if (i121) return 32+lowesttable[i121>>56];
+                       else      return 40+lowesttable[i12>>56];
+                       }
+               else {
+                       u8 i122 = i<<8;
+                       if (i122) return 48+lowesttable[i122>>56];
+                       else      return 56+lowesttable[i>>56];
+                       }
+               }
+#else
+       u4 i1 = i<<16;
+       if (i1) {
+               u4 i11 = i1<<8;
+               if (i11) return lowesttable[i11>>24];
+               else     return 8+lowesttable[i1>>24];
+               }
+       else {
+               u4 i12 = i<<8;
+               if (i12) return 16+lowesttable[i12>>24];
+               else     return 24+lowesttable[i>>24];
+               }
+#endif
+}
+
+
+/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
+
+static void setbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] |= 
+         ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] &= 
+          ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+          ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
+}
+
+static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+           ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
+}
+
+
+/***************** Funktion: clearbitfield ************************************
+       
+       l"oscht ein ganzes Bitfeld
+       
+******************************************************************************/
+
+static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
+{ 
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] = 0;
+}
+
+/************** Funktion: maskfieldwithfield **********************************
+       
+       Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
+       wird mit dem Ergebnis "uberschrieben 
+       
+******************************************************************************/
+       
+static void maskfieldwithfield (bitfieldtype* bitfield, 
+                                bitfieldtype *maskfield, u4 fieldsize)
+{
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
+}
+
+
+/************** Funktion: findnextsetbit **************************************
+
+       Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
+       und liefert die Nummer dieses Bits.
+       Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
+       ist, dann wird fieldsize zur"uckgeliefte.
+
+******************************************************************************/
+
+static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern = bitfield[bitnumber/BITFIELDBITS];
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+/************ Funktion: findnextcombination_set_unset *************************
+
+       funktioniert wie findnextsetbit, allerdings sucht diese Funktion
+       nach einer Stelle, an der gleichzeitig ein Bit im ersten
+       Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
+       Bit nicht gesetzt ist.
+
+******************************************************************************/
+
+static u4 findnextcombination_set_unset 
+       (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern =     bitfield1[bitnumber/BITFIELDBITS] 
+                         & (~bitfield2[bitnumber/BITFIELDBITS]);
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+
+/************** Funktion: memlist_init ****************************************
+
+       initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
+       mit memlist_addrange).
+
+******************************************************************************/
+
+static void memlist_init ()
+{
+       u4 i;
+       for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
+       clearbitfield (memlistbits, DIFFERENTSIZES);
+       bigmemlist = NULL;
+}
+
+
+/************** Funktion: memlist_addrange ************************************
+
+       f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
+       hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
+       Verkettungszeiger hineingeschrieben).
+
+******************************************************************************/
+
+static void memlist_addrange (u4 freestart, u4 freesize)
+{
+       if (freesize>=DIFFERENTSIZES) {
+               bigmemarea *m = (bigmemarea*) (heap+freestart);
+               m -> next = bigmemlist;
+               m -> size = freesize;
+               bigmemlist = m;
+               }
+       else {
+               if (freesize*BLOCKSIZE>=sizeof(memarea)) {
+                       memarea *m = (memarea*) (heap+freestart);
+                       m -> next = memlist[freesize];
+                       memlist[freesize] = m;
+                       setbit (memlistbits, freesize);
+                       }
+               }
+}
+
+
+/************** Funktion: memlist_getsuitable *********************************
+
+       sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
+       genau die gew"unschte L"ange hat.
+       Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
+       (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
+       Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
+       
+       Return (in Referenzparametern): 
+               *freestart: Anfang des freien Speichers
+               *freelength: L"ange dieses Speicherbereiches
+
+       Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
+       wird in '*freelength' 0 hineingeschrieben.
+       
+******************************************************************************/                
+
+static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
+{
+       bigmemarea *m;
+       bigmemarea *prevm = NULL;
+       
+       if (length<DIFFERENTSIZES) {
+               u4 firstfreelength;
+
+               if (memlist[length]) {
+                       firstfreelength = length;
+                       }
+               else {
+                       firstfreelength = findnextsetbit 
+                               (memlistbits, DIFFERENTSIZES, length+3); 
+                               /* wenn kein passender Block da ist, dann gleich nach */
+                               /* einem etwas gr"osseren suchen, damit keine kleinen */
+                               /* St"uckchen "ubrigbleiben */
+                       }
+                       
+               if (firstfreelength<DIFFERENTSIZES) {
+                       memarea *m = memlist[firstfreelength];
+                       memlist[firstfreelength] = m->next;             
+                       if (!m->next) clearbit (memlistbits, firstfreelength);
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = firstfreelength;
+                       return;
+                       }
+               }
+
+       m = bigmemlist;
+       while (m) {
+               if (m->size >= length) {
+                       if (prevm) prevm->next = m->next;                                       
+                               else   bigmemlist = m->next;
+                       
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = m->size;
+                       return ;                        
+                       }
+
+               prevm = m;
+               m = m->next;
+               }
+       
+       *freelength=0;
+}
+
+
+
+
+
+/******************* Funktion: mark *******************************************
+
+       Markiert ein m"oglicherweise g"ultiges Objekt.
+       Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
+       am Heap zeigt, dann wird eben gar nichts markiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend);
+
+static void mark (heapblock *obj)
+{
+       u4 blocknum,objectend;
+
+       if ((long) obj & (BLOCKSIZE-1)) return;
+       
+       if (obj<heap) return;
+       if (obj>=(heap+topofheap) ) return;
+
+       blocknum = obj-heap;
+       if ( isbitclear(startbits, blocknum) ) return;
+       if ( isbitset(markbits, blocknum) ) return;
+
+       setbit (markbits, blocknum);
+       
+       if ( isbitclear(referencebits, blocknum) ) return;
+
+       objectend = findnextsetbit (startbits, topofheap, blocknum+1);
+       markreferences ((void**)obj, (void**) (heap+objectend) );
+}
+
+
+/******************** Funktion: markreferences ********************************
+
+       Geht einen Speicherbereich durch, und markiert alle Objekte, auf
+       die von diesem Bereich aus irgendeine Referenz existiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend)
+{
+       void **ptr;
+       
+       for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
+}
+
+
+/******************* Funktion: markstack **************************************
+
+        Marks all objects that are referenced by the (C-)stacks of
+        all live threads.
+
+       (The stack-bottom is to be specified in the call to heap_init).
+
+******************************************************************************/
+
+static void markstack ()                   /* schani */
+{
+       void *dummy;
+       void **top_of_stack = &dummy;
+
+#ifdef USE_THREADS
+       thread *aThread;
+
+       for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
+               mark((heapblock*)aThread);
+               if (aThread == currentThread) {
+                       if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
+                       else    
+                               markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
+                       }
+               else {
+                       if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd,
+                                               (void**)CONTEXT(aThread).usedStackTop + 16);
+                       else    
+                               markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
+                                               (void**)CONTEXT(aThread).stackEnd);
+                       }
+               }
+
+       markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+#else
+       if (top_of_stack > bottom_of_stack)
+               markreferences(bottom_of_stack, top_of_stack);
+       else
+               markreferences(top_of_stack, bottom_of_stack);
+#endif
+}
+
+
+
+/**************** Funktion: searchlivefinalizees *****************************
+
+       geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
+       (livefinalizees), und tr"agt alle nicht mehr markierten in die
+       Liste deadfinalizess ein (allerdings werden sie vorher noch als
+       erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
+       
+*****************************************************************************/ 
+
+static void searchlivefinalizees ()
+{
+       finalizernode *fn = livefinalizees;
+       finalizernode *lastlive = NULL;
+               
+       while (fn) {
+       
+               /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
+               if (isbitclear (markbits, fn->objstart)) {
+                       finalizernode *nextfn = fn->next;
+
+                       mark (heap + fn->objstart); 
+
+                       if (lastlive) lastlive -> next = nextfn;
+                                      else livefinalizees = nextfn;
+
+                       fn -> next = deadfinalizees;
+                       deadfinalizees = fn;
+                       
+                       fn = nextfn;
+                       }
+               else {  
+                       lastlive = fn;
+                       fn = fn->next;
+                       }
+               }
+}
+
+
+
+/********************** Funktion: finalizedead *******************************
+
+       ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
+       Liste auf.
+       Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
+       (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
+       globalen Variablen in lokale Variblen kopiert werden 
+       (Reentrant-F"ahigkeit!!!)
+        
+******************************************************************************/
+
+static void finalizedead()
+{
+       finalizernode *fn = deadfinalizees;
+       deadfinalizees = NULL;
+       
+       while (fn) {
+               finalizernode *nextfn = fn->next;
+               
+               asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
+               FREE (fn, finalizernode);
+               
+               fn = nextfn;
+               }
+
+}
+
+
+
+/****************** Funktion: heap_docollect **********************************
+       
+       F"uhrt eine vollst"andige Garbage Collection durch
+       
+******************************************************************************/
+
+static void heap_docollect ()
+{
+       u4 freestart,freeend;
+       void **p;
+       bitfieldtype *dummy;
+       u4 heapfreemem;
+       u4 oldfillgrade;
+
+
+       if (runverbose) {
+               fprintf(stderr, "doing garbage collection\n");
+               }
+               /* alle Markierungsbits l"oschen */
+       clearbitfield (markbits, topofheap);
+
+               /* Alle vom Stack referenzierten Objekte markieren */
+       asm_dumpregistersandcall (markstack);
+
+               /* Alle von globalen Variablen erreichbaren Objekte markieren */
+       p = chain_first (allglobalreferences);
+       while (p) {
+               mark (*p);
+               p = chain_next (allglobalreferences);   
+               }
+
+               /* alle Objekte durchsehen, die eine finalizer-Methode haben */
+       searchlivefinalizees();
+
+               /* alle Reference-Bits l"oschen, deren Objekte nicht */
+               /* mehr erreichbar sind */
+       maskfieldwithfield (referencebits, markbits, topofheap);
+
+
+               /* Freispeicherliste initialisieren */
+       memlist_init ();
+       
+       
+               /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
+
+       heapfreemem = 0;
+       freeend=0;
+       for (;;) {
+                       /* Anfang des n"achsten freien Bereiches suchen */
+               freestart = findnextcombination_set_unset 
+                       (startbits, markbits, topofheap, freeend);
+
+                       /* Wenn es keinen freien Bereich mehr gibt -> fertig */
+               if (freestart>=topofheap) goto freememfinished;
+
+                       /* Anfang des freien Bereiches markieren */
+               setbit (markbits, freestart);
+
+                       /* Ende des freien Bereiches suchen */          
+               freeend = findnextsetbit (markbits, topofheap, freestart+1);
+
+                       /* Freien Bereich in Freispeicherliste einh"angen */
+               memlist_addrange (freestart, freeend-freestart);
+
+                       /* Menge des freien Speichers mitnotieren */
+               heapfreemem += (freeend-freestart);
+               }
+
+       freememfinished:
+
+               /* Die Rollen von markbits und startbits vertauschen */ 
+       dummy = markbits;
+       markbits = startbits;
+       startbits = dummy;
+
+
+               /* Threashold-Wert f"ur n"achstes Collect */
+       oldfillgrade = heapfillgrade;
+       heapfillgrade = topofheap - heapfreemem;
+       collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
+
+               /* Eventuell eine Meldung ausgeben */
+       if (collectverbose) {
+               sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
+                 (int) (oldfillgrade * BLOCKSIZE), 
+                 (int) (heapfillgrade * BLOCKSIZE) );
+               dolog ();
+               }
+
+
+               
+               /* alle gerade unerreichbar gewordenen Objekte mit 
+                  finalize-Methoden jetzt finalisieren.
+                  Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
+       finalizedead ();
+       
+}
+
+/************************* Function: gc_init **********************************
+
+        Initializes the garbage collection thread mechanism.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+iMux gcStartMutex;
+iMux gcThreadMutex;
+iCv gcConditionStart;
+iCv gcConditionDone;
+
+void
+gc_init (void)
+{
+    gcStartMutex.holder = 0;
+    gcStartMutex.count = 0;
+    gcStartMutex.muxWaiters = 0;
+
+    gcThreadMutex.holder = 0;
+    gcThreadMutex.count = 0;
+    gcThreadMutex.muxWaiters = 0;
+
+    gcConditionStart.cvWaiters = 0;
+    gcConditionStart.mux = 0;
+
+    gcConditionDone.cvWaiters = 0;
+    gcConditionDone.mux = 0;
+}    
+#else
+void
+gc_init (void)
+{
+}
+#endif
+
+/************************* Function: gc_thread ********************************
+
+        In an endless loop waits for a condition to be posted, then
+       garbage collects the heap.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+void
+gc_thread (void)
+{
+    intsRestore();           /* all threads start with interrupts disabled */
+
+       assert(blockInts == 0);
+
+    lock_mutex(&gcThreadMutex);
+
+    for (;;)
+    {
+               wait_cond(&gcThreadMutex, &gcConditionStart, 0);
+
+               intsDisable();
+               heap_docollect();
+               intsRestore();
+
+               signal_cond(&gcConditionDone);
+    }
+}
+#endif
+
+void
+gc_call (void)
+{
+#ifdef USE_THREADS
+    lock_mutex(&gcThreadMutex);
+
+    signal_cond(&gcConditionStart);
+    wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+
+    unlock_mutex(&gcThreadMutex);
+#else
+    heap_docollect();
+#endif
+}
+
+
+/************************* Funktion: heap_init ********************************
+
+       Initialisiert den Garbage Collector.
+       Parameter: 
+               heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
+               heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
+                                  GC durchgef"uhrt werden soll.
+               stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
+                              Referenzen auf Objekte stehen k"onnen.                  
+                                          
+******************************************************************************/
+
+void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
+{
+
+#ifdef TRACECALLARGS
+
+       heapsize = ALIGN (heapbytesize, getpagesize());
+       heapsize = heapsize/BLOCKSIZE;
+       heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
+              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
+       if (heap != (void *) 0x10000000) {
+               perror("mmap");
+               printf("address = %p\n", heap);
+               panic("mmap failed\n");
+               }
+
+#else
+
+       heapsize = ALIGN (heapbytesize, 1024);
+       heapsize = heapsize/BLOCKSIZE;
+       heap = MNEW (heapblock, heapsize);
+
+#endif
+
+       topofheap = 0;
+       startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       clearbitfield (startbits, heapsize);
+       clearbitfield (markbits, heapsize);
+       clearbitfield (referencebits, heapsize);
+
+       heapfillgrade = 0;
+       collectthreashold = heapbytestartsize/BLOCKSIZE;
+       allglobalreferences = chain_new ();
+       bottom_of_stack = stackbottom;
+
+       livefinalizees = NULL;
+       deadfinalizees = NULL;
+}
+
+
+/****************** Funktion: heap_close **************************************
+
+       Gibt allen ben"otigten Speicher frei
+
+******************************************************************************/
+
+void heap_close ()
+{
+#ifndef TRACECALLARGS
+       MFREE (heap, heapblock, heapsize); */
+#endif
+       MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
+       chain_free (allglobalreferences);
+
+       while (livefinalizees) {
+               finalizernode *n = livefinalizees->next;
+               FREE (livefinalizees, finalizernode);
+               livefinalizees = n;
+               }
+}
+
+
+/***************** Funktion: heap_addreference ********************************
+
+       Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
+       auf Objekte gespeichert sein kann.
+
+******************************************************************************/
+
+void heap_addreference (void **reflocation)
+{
+       intsDisable();                     /* schani */
+
+       chain_addlast (allglobalreferences, reflocation);
+
+       intsRestore();                    /* schani */
+}
+
+
+
+/***************** Funktion: heap_allocate ************************************
+
+       Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
+       (in Byte angegeben) haben muss.
+       Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
+       Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
+       Zus"atzlich wird durch den Parameter 'references' angegeben, ob
+       in das angelegte Objekt Referenzen auf andere Objekte eingetragen
+       werden k"onnten. 
+       (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
+       Im Zweifelsfalle immer references=true verwenden.
+
+******************************************************************************/
+
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
+{
+       u4 freestart,freelength;
+       u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+       
+       intsDisable();                        /* schani */
+
+       memlist_getsuitable (&freestart, &freelength, length);
+
+onemoretry:
+       if (!freelength) {
+               if (    (topofheap+length > collectthreashold) 
+                    || (topofheap+length > heapsize) ) {
+
+                       intsRestore();
+                       gc_call();
+                       intsDisable();
+                       
+                       memlist_getsuitable (&freestart, &freelength, length);
+                       if (freelength) goto onemoretry;
+                       }
+               
+               if (topofheap+length > heapsize) {
+                       sprintf (logtext, "Heap-Allocation failed for %d bytes", 
+                           (int) bytelength);
+                       dolog();
+                       intsRestore();            /* schani */
+                       return NULL;
+                       }
+                       
+               freestart = topofheap;
+               freelength = length;
+               setbit (startbits, topofheap);
+               topofheap += length;
+               }
+       else {
+               if (freelength>length) {
+                       setbit (startbits, freestart+length);
+                       memlist_addrange (freestart+length, freelength-length);
+                       }
+               }
+               
+       if (references) setbit (referencebits, freestart);
+
+       heapfillgrade += length;
+
+       if (finalizer) {
+               finalizernode *n = NEW(finalizernode);
+               n -> next = livefinalizees;
+               n -> objstart = freestart;
+               n -> finalizer = finalizer;
+               livefinalizees = n;
+               }
+       
+       intsRestore();                   /* schani */
+
+       if (runverbose) {
+               sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
+               dolog ();
+               }
+
+       return (void*) (heap + freestart);
+}
+
+
+
+
diff --git a/tables.h b/tables.h
new file mode 100644 (file)
index 0000000..80f7893
--- /dev/null
+++ b/tables.h
@@ -0,0 +1,63 @@
+/****************************** tables.h ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/11/20
+
+*******************************************************************************/
+
+extern bool collectverbose;
+
+
+#define CLASS(name)     (unicode_getclasslink(unicode_new_char(name)))
+
+typedef void (*stringdeleter) ( java_objectheader *string );
+
+
+void suck_init (char *classpath);
+bool suck_start (unicode *name);
+void suck_stop ();
+void suck_nbytes (u1 *buffer, u4 len);
+void skip_nbytes (u4 len);
+u1 suck_u1 ();
+s1 suck_s1 ();
+u2 suck_u2 ();
+s2 suck_s2 ();
+u4 suck_u4 ();
+s4 suck_s4 ();
+u8 suck_u8 ();
+s8 suck_s8 ();
+float suck_float ();
+double suck_double ();
+
+
+void unicode_init ();
+void unicode_close (stringdeleter del);
+void unicode_display (unicode *u);
+void unicode_sprint (char *buffer, unicode *u);
+void unicode_fprint (FILE *file, unicode *u);
+unicode *unicode_new_u2 (u2 *text, u2 length);
+unicode *unicode_new_char (char *text);
+void unicode_setclasslink (unicode *u, classinfo *class);
+classinfo *unicode_getclasslink (unicode *u);
+void unicode_unlinkclass (unicode *u);
+void unicode_setstringlink (unicode *u, java_objectheader *str);
+void unicode_unlinkstring (unicode *u);
+void unicode_show ();
+
+u2 desc_to_type (unicode *descriptor);
+u2 desc_typesize (unicode *descriptor);
+
+
+void heap_init (u4 size, u4 startsize, void **stackbottom);
+void heap_close ();
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer);
+void heap_addreference (void **reflocation);
+
+void gc_init (void);
+void gc_thread (void);
+void gc_call (void);
diff --git a/tests/JavaPerformance.java b/tests/JavaPerformance.java
new file mode 100644 (file)
index 0000000..049fdb6
--- /dev/null
@@ -0,0 +1,396 @@
+import java.util.*;
+import java.io.*;
+
+class SubClass1 extends Object {
+}
+
+class SubClass2 extends Object {
+  int a,b,c;
+
+  SubClass2 (int aa, int ab, int ac) {
+    a = aa;
+    b = ab;
+    c = ac;
+  }
+
+  public void methodWithLocalAccess () {
+    int la,lb,lc;
+    for (int i=0; i<JavaPerformance.MAXCOUNT; i++) {
+      la = 5;
+      lb = 6;
+      lc = 7;
+    }
+  }
+
+  public void methodWithInstanceAccess () {
+    for (int i=0; i<JavaPerformance.MAXCOUNT; i++) {    
+      a = 5;
+      b = 6;
+      c = 7;
+    }
+  }  
+}
+
+class List extends Object {
+
+  static Random r = new Random();
+  
+  List[] data;
+  char[] memory;
+  
+  List (int depth) {
+    memory = new char[512];
+    if (depth>0) {
+      int length = 1+Math.abs(r.nextInt())%5;
+      data = new List[length];
+      for (int i=0; i<length; i++)
+        data[i] = new List (depth-1);
+    }
+  }
+}
+
+public class JavaPerformance {
+
+  static final int MAXCOUNT = 500000;  
+  static Throwable aThrowable = new Throwable ();
+  
+  public JavaPerformance () {
+    super();
+  }
+
+  // static
+  
+  static public int staticCall () {
+    return 0;
+  }
+
+  static public final int staticFinalCall () {
+    return 0;
+  }
+  
+  static public synchronized int synchronizedStaticCall () {
+    return 0;
+  }
+  
+  static public void throwingStaticCall () throws Throwable {
+    throw new Throwable ();
+  }
+
+  // methods
+  
+  public int methodCall () {
+    return 0;
+  }
+
+  public final int finalMethodCall () {
+    return 0;
+  }
+
+  static public synchronized int synchronizedMethodCall () {
+    return 0;
+  }
+  
+  static public void throwingMethodCall () throws Throwable {
+    throw new Throwable ();
+  }
+
+  // ggT
+
+  public static int ggT (int x, int y) {
+    while (x!=y) {
+      if (x<y) y = y-x; else x = x-y;
+    }
+    return x;
+  }
+
+  public static long fak (long x) {
+    if (x>1)
+      return x*fak(x-1);
+    else
+      return 1;
+  }
+  
+  public static void arithmeticTest () {
+    System.out.println ("Arithmetic time");
+    System.out.println ();
+
+    System.out.print ("ggT (24,42)...");
+    long l = System.currentTimeMillis();
+    for (int i = 0; i<MAXCOUNT; i++)
+      ggT (24,42);
+    long e = System.currentTimeMillis();
+    System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);
+    System.out.println (")");
+
+    System.out.print ("13!...");
+    l = System.currentTimeMillis();
+    for (int i = 0; i<MAXCOUNT; i++)
+      fak (13);
+    e = System.currentTimeMillis();    
+    System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);
+    System.out.println (")");    
+  }
+
+  public static void memoryTest () {
+    System.out.println ("Memory time");
+    System.out.println ();
+
+    System.out.print ("Object creation...");
+    long l = System.currentTimeMillis();
+    for (int i = 0; i<MAXCOUNT; i++)
+      new Object ();
+    long e = System.currentTimeMillis();        
+    System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);
+    System.out.println (")");
+
+    System.out.print ("Subclass creation...");
+    l = System.currentTimeMillis();
+    for (int i = 0; i<MAXCOUNT; i++)
+      new SubClass1 ();
+    e = System.currentTimeMillis();        
+    System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);
+    System.out.println (")");    
+
+    System.out.print ("Subclass creation with constructor call...");
+    l = System.currentTimeMillis();
+    for (int i = 0; i<MAXCOUNT; i++)
+      new SubClass2 (1,2,3);
+    e = System.currentTimeMillis();        
+    System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");    
+    System.out.print(e-l);    
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);    
+    System.out.println (")");    
+
+    System.out.print ("List generation (GC test)...");
+    l = System.currentTimeMillis();
+    for (int i = 0; i<250; i++)
+      new List (5);
+    e = System.currentTimeMillis();        
+    System.out.print ("(");
+    System.out.print (((double) e-l)/250);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (250);    
+    System.out.println (")");    
+    
+  }
+
+  public static void methodTest () {
+    SubClass2 object = new SubClass2 (1,2,3);
+    
+    System.out.println ("Method execution time");
+    System.out.println ();
+    
+    System.out.print ("Method with access only to local variables...");
+    long l = System.currentTimeMillis();
+    object.methodWithLocalAccess ();
+    long e = System.currentTimeMillis();        
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+
+     System.out.print ("Method with access only to instance variables...");
+     l = System.currentTimeMillis();
+     object.methodWithInstanceAccess ();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+  }
+  
+  public static void callTest () {
+    JavaPerformance object = new JavaPerformance ();
+
+    System.out.println ("Calling time");
+    System.out.println ();
+    System.out.print ("Static function call...");
+    long l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       staticCall ();
+     long e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+
+    System.out.print ("Static final function call...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       staticFinalCall ();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+
+     System.out.print ("Static synchronized function call...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       synchronizedStaticCall();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+     
+     System.out.print ("Static function call in try catch block...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       try {
+         staticCall ();
+       } catch (Throwable a) {
+       }
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+    
+    System.out.print ("Static exception throwing function call...");
+    l = System.currentTimeMillis();
+    for (int i = 0; i<5000; i++)
+      try {
+        throwingStaticCall ();
+      } catch (Throwable exp) {
+      }
+    e = System.currentTimeMillis();        
+    System.out.print ("(");
+    System.out.print (((double) e-l)/5000);
+    System.out.print ("ms ");    
+    System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (5000);
+    System.out.println (")");
+
+
+    System.out.print ("Method call...");
+    l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       object.methodCall ();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+
+    System.out.print ("Final method call...");
+    l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       object.finalMethodCall ();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+
+     System.out.print ("Synchronized method call...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       object.synchronizedMethodCall();
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+     
+     System.out.print ("Method call in try catch block...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<MAXCOUNT; i++)
+       try {
+         object.methodCall ();
+       } catch (Throwable a) {
+       }
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/MAXCOUNT);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (MAXCOUNT);     
+     System.out.println (")");
+    
+     System.out.print ("Exception throwing method call...");
+     l = System.currentTimeMillis();
+     for (int i = 0; i<50000; i++)
+       try {
+         object.throwingMethodCall ();
+       } catch (Throwable exp) {
+       }
+     e = System.currentTimeMillis();         
+     System.out.print ("(");
+    System.out.print (((double) e-l)/5000);
+    System.out.print ("ms ");     
+     System.out.print(e-l);
+    System.out.print ("ms/");
+    System.out.print (5000);
+     System.out.println (")");
+  }
+
+  public static final void main (String[] args) {
+    long l = System.currentTimeMillis();    
+    arithmeticTest ();
+    System.out.println ();
+    callTest ();
+    System.out.println ();
+    methodTest ();
+    System.out.println ();    
+    memoryTest ();
+    System.out.println ();
+    System.out.print ("Overall time ");
+    System.out.print(System.currentTimeMillis()-l);
+    System.out.println ("ms");
+  }
+}
diff --git a/tests/a.java b/tests/a.java
new file mode 100644 (file)
index 0000000..c81bc22
--- /dev/null
@@ -0,0 +1,5 @@
+public interface a extends b
+{
+       public void do_a ();
+       public void do_a2 ();
+}
diff --git a/tests/array.java b/tests/array.java
new file mode 100644 (file)
index 0000000..cf173cd
--- /dev/null
@@ -0,0 +1,7 @@
+public class array extends Object
+{
+    public static void main (String args[])
+    {
+       System.out.println(args[0]);
+    }
+}
diff --git a/tests/b.java b/tests/b.java
new file mode 100644 (file)
index 0000000..86f11e6
--- /dev/null
@@ -0,0 +1,4 @@
+public interface b 
+{
+       public void do_b ();
+}
diff --git a/tests/counter.java b/tests/counter.java
new file mode 100644 (file)
index 0000000..b14ac70
--- /dev/null
@@ -0,0 +1,20 @@
+public class counter {
+       static public void main (String [] s) {
+       
+               int n = Integer.parseInt (s[0]);
+       
+               System.out.print ("Counting ");
+               System.out.print (n);
+               System.out.println (" times from 0 to 9999..."); 
+               
+               int i,j;
+               for (j=0; j<n; j++) 
+                       for (i=0; i<10000; i++) {
+                               }
+                       
+               System.out.println ("... done");
+               }
+       
+       }
+       
+       
\ No newline at end of file
diff --git a/tests/extest.java b/tests/extest.java
new file mode 100644 (file)
index 0000000..97db7b8
--- /dev/null
@@ -0,0 +1,18 @@
+import java.io.*;
+
+public class extest extends Object
+{
+    public static void main (String args[])
+    {
+        try
+        {
+            RandomAccessFile file = new RandomAccessFile("test.file", "rw");
+            
+            file.seek(file.length());
+        }
+        catch (Exception exc)
+        {
+            System.out.println("could not open file");
+        }
+    }
+}
diff --git a/tests/filter.java b/tests/filter.java
new file mode 100644 (file)
index 0000000..375d114
--- /dev/null
@@ -0,0 +1,29 @@
+import java.io.*;
+
+
+public class filter {
+   public static void main(String argv[]) {
+   
+      DataInputStream in = new DataInputStream(System.in);
+
+      
+      try {
+         while (true) {
+            byte b = in.readByte();
+            if (b <= 128) { 
+               int x = b;
+               System.out.println("BYTE: " + x);
+            } else {
+               String x = "non ascii: " + b;
+               System.out.println(x);
+            }
+         }
+      }
+      catch (IOException e) {
+         System.out.println("-- END OF FILE --");
+      }
+      finally {
+         System.out.println("--- Cool finally ---");
+      }
+   }
+}
diff --git a/tests/fintest.java b/tests/fintest.java
new file mode 100644 (file)
index 0000000..228b988
--- /dev/null
@@ -0,0 +1,30 @@
+public class fintest {
+       public int num;
+       
+       public fintest (int n) { num = n; }
+
+       public void finalize () {
+               System.out.print ("finalized ");
+               System.out.print (num);
+               System.out.println (". object");
+               }
+
+       public static void main (String[] s) {
+               int i;
+               fintest f=null;
+               
+               for (i=0; i<100; i++) {
+                       System.out.print (i);
+                       System.out.println (". Objekt wird angelegt");
+                       f = new fintest(i);
+                       byte[] b = new byte[1000000];
+                       b[0] = 0;
+                       }
+
+               Runtime.getRuntime().exit(0);
+       
+               }
+               
+       }
+
+       
\ No newline at end of file
diff --git a/tests/fp.java b/tests/fp.java
new file mode 100644 (file)
index 0000000..78776c4
--- /dev/null
@@ -0,0 +1,33 @@
+public class fp {
+       public static void main(String [] s) {
+
+               float a=10,b=10;
+               int i;
+               
+               for (i=0; i<1000; i++) {
+                       a*=b;
+                       p(a);
+                       }
+               
+               for (a=0; a<1; a+=0.2) {
+                       for (b=0; b<1; b+=0.2) {
+                               System.out.println ("-----------");
+                               p(a);
+                               p(b);
+                               p(a+b);
+                               p(a-b);
+                               p(a*b);
+                               p(a/b);
+                               }
+                       }
+               }
+               
+               
+       public static void p(double d) {
+               System.out.println (d);
+               }
+       public static void p(float d) {
+               System.out.println (d);
+               }
+
+       }
diff --git a/tests/fptest.java b/tests/fptest.java
new file mode 100644 (file)
index 0000000..537236b
--- /dev/null
@@ -0,0 +1,268 @@
+/***************************** alpha/ngen.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Contains the codegenerator for an Alpha processor.
+       This module generates Alpha machine code for a sequence of
+       pseudo commands (ICMDs).
+
+       Authors: Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+                Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/08/10
+
+*******************************************************************************/
+
+public class fptest {
+       public static void main(String [] s) {
+
+               float  fnan  = Float.NaN;
+               float  fpinf = Float.POSITIVE_INFINITY;
+               float  fninf = Float.NEGATIVE_INFINITY;
+               float  fmax  = Float.MAX_VALUE;
+               float  fmin  = Float.MIN_VALUE;
+               float  f1    = 0F;
+               float  f2    = 0F;
+
+               double dnan  = Double.NaN;
+               double dpinf = Double.POSITIVE_INFINITY;
+               double dninf = Double.NEGATIVE_INFINITY;
+               double dmax  = Double.MAX_VALUE;
+               double dmin  = Double.MIN_VALUE;
+               double d1    = 0D;
+               double d2    = 0D;
+               
+               p("---------------------------- tests NaNs and Infs -------------------");
+               p("------------------- print NaNs and Infs");
+
+               p("NaNQ ", fnan);
+               p("+INF ", fpinf);
+               p("-INF ", fninf);
+
+               p("NaNQ ", dnan);
+               p("+INF ", dpinf);
+               p("-INF ", dninf);
+
+               p("------------------- test zero division");
+
+               zerodiv("0 / 0 = NaNQ ",  0F, f1);
+               zerodiv("+ / 0 = +INF ",  5F, f1);
+               zerodiv("- / 0 = -INF ", -5F, f1);
+
+               zerodiv("0 / 0 = NaNQ ",  0D, d1);
+               zerodiv("+ / 0 = +INF ",  5D, d1);
+               zerodiv("- / 0 = -INF ", -5D, d1);
+
+               p("------------------- test conversions");
+               testfcvt("NaNQ", fnan, dnan);
+               testfcvt("+INF", fpinf, dpinf);
+               testfcvt("-INF", fninf, dninf);
+               testfcvt(" MAX",  fmax, dmax);
+               testfcvt(" MIN",  fmin, dmin);
+               testfcvt("MAXINT-1",  2147483646.0F, 2147483646.0D);
+               testfcvt("MAXINT+0",  2147483647.0F, 2147483647.0D);
+               testfcvt("MAXINT+1",  2147483648.0F, 2147483648.0D);
+               testfcvt("-MAXINT+1",  -2147483647.0F, -2147483647.0D);
+               testfcvt("-MAXINT+0",  -2147483648.0F, -2147483648.0D);
+               testfcvt("-MAXINT-1",  -2147483649.0F, -2147483649.0D);
+               testfcvt("MAXLNG-1",  9223372036854775806.0F, 9223372036854775806.0D);
+               testfcvt("MAXLNG+0",  9223372036854775807.0F, 9223372036854775807.0D);
+               testfcvt("MAXLNG+1",  9223372036854775808.0F, 9223372036854775808.0D);
+               testfcvt("-MAXLNG+1",  -9223372036854775807.0F, -9223372036854775807.0D);
+               testfcvt("-MAXLNG+0",  -9223372036854775808.0F, -9223372036854775808.0D);
+               testfcvt("-MAXLNG-1",  -9223372036854775809.0F, -9223372036854775809.0D);
+
+               p("------------------- test NaNQ op value");
+               testfops("NaNQ", "5.0", fnan, 5F, dnan, 5D);
+               testfcmp("NaNQ", "5.0", fnan, 5F, dnan, 5D);
+
+               p("------------------- test value op NaNQ");
+               testfops("5.0", "NaNQ", 5F, fnan, 5D, dnan);
+               testfcmp("5.0", "NaNQ", 5F, fnan, 5D, dnan);
+
+               p("------------------- test +INF op value");
+               testfops("+INF", "5.0", fpinf, 5F, dpinf, 5D);
+               testfcmp("+INF", "5.0", fpinf, 5F, dpinf, 5D);
+
+               p("------------------- test +INF op value");
+               testfops("5.0", "+INF", 5F, fpinf, 5D, dpinf);
+               testfcmp("5.0", "+INF", 5F, fpinf, 5D, dpinf);
+
+               p("------------------- test -INF op value");
+               testfops("-INF", "5.0", fninf, 5F, dninf, 5D);
+               testfcmp("-INF", "5.0", fninf, 5F, dninf, 5D);
+
+               p("------------------- test -INF op value");
+               testfops("5.0", "-INF", 5F, fninf, 5D, dninf);
+               testfcmp("5.0", "-INF", 5F, fninf, 5D, dninf);
+
+               p("------------------- test MAX op value");
+               testfops("MAX", "5.0", fmax, 5F, dmax, 5D);
+
+               p("------------------- test value op MAX");
+               testfops("5.0", "MAX", 5F, fmax, 5D, dmax);
+
+               p("------------------- test MIN op value");
+               testfops("MIN", "5.0", fmin, 5F, dmin, 5D);
+
+               p("------------------- test value op MIN");
+               testfops("5.0", "MIN", 5F, fmin, 5D, dmin);
+
+               }
+               
+       public static void zerodiv(String s, float f1, float f2) {
+               p(s, f1 / f2);
+               }
+
+       public static void zerodiv(String s, double d1, double d2) {
+               p(s, d1 / d2);
+               }
+
+       public static void testfcvt(String s1, float f1, double d1) {
+               p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (int)  f1);
+               p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (int)  d1);
+               p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (long) f1);
+               p("convert " + s1 + " (" + f1 + "," + d1 + ") to ", (long) d1);
+               }
+
+       public static void testfops(String s1, String s2, float f1, float f2,
+                                  double d1, double d2) {
+               p(s1 + " + " + s2 + " = ", f1 + f2);
+               p(s1 + " - " + s2 + " = ", f1 - f2);
+               p(s1 + " * " + s2 + " = ", f1 * f2);
+               p(s1 + " / " + s2 + " = ", f1 / f2);
+               p(s1 + " % " + s2 + " = ", f1 % f2);
+               p(s1 + " + " + s2 + " = ", d1 + d2);
+               p(s1 + " - " + s2 + " = ", d1 - d2);
+               p(s1 + " * " + s2 + " = ", d1 * d2);
+               p(s1 + " / " + s2 + " = ", d1 / d2);
+               p(s1 + " % " + s2 + " = ", d1 % d2);
+               }
+
+       public static void testfcmp(String s1, String s2, float f1, float f2,
+                                  double d1, double d2) {
+
+               if ( (f1 == f2)) p(" (" + s1 + " == " + s2 + ") = true");
+               else             p(" (" + s1 + " == " + s2 + ") = false");
+               if ( (f1 != f2)) p(" (" + s1 + " != " + s2 + ") = true");
+               else             p(" (" + s1 + " != " + s2 + ") = false");
+               if ( (f1 <  f2)) p(" (" + s1 + " <  " + s2 + ") = true");
+               else             p(" (" + s1 + " <  " + s2 + ") = false");
+               if ( (f1 <= f2)) p(" (" + s1 + " <= " + s2 + ") = true");
+               else             p(" (" + s1 + " <= " + s2 + ") = false");
+               if ( (f1 >  f2)) p(" (" + s1 + " >  " + s2 + ") = true");
+               else             p(" (" + s1 + " >  " + s2 + ") = false");
+               if ( (f1 >= f2)) p(" (" + s1 + " >= " + s2 + ") = true");
+               else             p(" (" + s1 + " >= " + s2 + ") = false");
+
+               if (!(f1 == f2)) p("!(" + s1 + " == " + s2 + ") = true");
+               else             p("!(" + s1 + " == " + s2 + ") = false");
+               if (!(f1 != f2)) p("!(" + s1 + " != " + s2 + ") = true");
+               else             p("!(" + s1 + " != " + s2 + ") = false");
+               if (!(f1 <  f2)) p("!(" + s1 + " <  " + s2 + ") = true");
+               else             p("!(" + s1 + " <  " + s2 + ") = false");
+               if (!(f1 <= f2)) p("!(" + s1 + " <= " + s2 + ") = true");
+               else             p("!(" + s1 + " <= " + s2 + ") = false");
+               if (!(f1 >  f2)) p("!(" + s1 + " >  " + s2 + ") = true");
+               else             p("!(" + s1 + " >  " + s2 + ") = false");
+               if (!(f1 >= f2)) p("!(" + s1 + " >= " + s2 + ") = true");
+               else             p("!(" + s1 + " >= " + s2 + ") = false");
+
+               if ( (d1 == d2)) p(" (" + s1 + " == " + s2 + ") = true");
+               else             p(" (" + s1 + " == " + s2 + ") = false");
+               if ( (d1 != d2)) p(" (" + s1 + " != " + s2 + ") = true");
+               else             p(" (" + s1 + " != " + s2 + ") = false");
+               if ( (d1 <  d2)) p(" (" + s1 + " <  " + s2 + ") = true");
+               else             p(" (" + s1 + " <  " + s2 + ") = false");
+               if ( (d1 <= d2)) p(" (" + s1 + " <= " + s2 + ") = true");
+               else             p(" (" + s1 + " <= " + s2 + ") = false");
+               if ( (d1 >  d2)) p(" (" + s1 + " >  " + s2 + ") = true");
+               else             p(" (" + s1 + " >  " + s2 + ") = false");
+               if ( (d1 >= d2)) p(" (" + s1 + " >= " + s2 + ") = true");
+               else             p(" (" + s1 + " >= " + s2 + ") = false");
+
+               if (!(d1 == d2)) p("!(" + s1 + " == " + s2 + ") = true");
+               else             p("!(" + s1 + " == " + s2 + ") = false");
+               if (!(d1 != d2)) p("!(" + s1 + " != " + s2 + ") = true");
+               else             p("!(" + s1 + " != " + s2 + ") = false");
+               if (!(d1 <  d2)) p("!(" + s1 + " <  " + s2 + ") = true");
+               else             p("!(" + s1 + " <  " + s2 + ") = false");
+               if (!(d1 <= d2)) p("!(" + s1 + " <= " + s2 + ") = true");
+               else             p("!(" + s1 + " <= " + s2 + ") = false");
+               if (!(d1 >  d2)) p("!(" + s1 + " >  " + s2 + ") = true");
+               else             p("!(" + s1 + " >  " + s2 + ") = false");
+               if (!(d1 >= d2)) p("!(" + s1 + " >= " + s2 + ") = true");
+               else             p("!(" + s1 + " >= " + s2 + ") = false");
+               }
+
+       // ********************* output methods ****************************
+
+       public static int linenum = 0;
+
+       public static void pnl() {
+               int i;
+
+               System.out.println();
+               for (i = 4 - Integer.toString(linenum).length(); i > 0; i--)
+                       System.out.print(' ');
+               System.out.print(linenum);
+               System.out.print(".    ");
+               linenum++;
+               }
+
+       public static void p(String a) {
+               System.out.print(a); pnl();
+               }
+       public static void p(boolean a) {
+               System.out.print(a); pnl();
+               }
+       public static void p(int a) {
+               System.out.print("int:    "); System.out.print(a); pnl();
+               }
+       public static void p(long a) {
+               System.out.print("long:   "); System.out.print(a); pnl();
+               }
+       public static void p(short a) {
+               System.out.print("short:  "); System.out.print(a); pnl();
+               }
+       public static void p(byte a) {
+               System.out.print("byte:   "); System.out.print(a); pnl();
+               }
+       public static void p(char a) {
+               System.out.print("char:   "); System.out.print((int)a); pnl();
+               }
+       public static void p(float a) {
+               System.out.print("float:  "); System.out.print(a); pnl();
+               }
+       public static void p(double a) {
+               System.out.print("double: "); System.out.print(a); pnl();
+               }
+
+       public static void p(String s, boolean i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s, int i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s, byte i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s, char i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s, short i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s, long l) { 
+               System.out.print(s); p(l);
+               }
+       public static void p(String s, float f) { 
+               System.out.print(s); p(f);
+               }
+       public static void p(String s, double d) {
+               System.out.print(s); p(d);
+               }
+
+       }
diff --git a/tests/ftest.java b/tests/ftest.java
new file mode 100644 (file)
index 0000000..6c67971
--- /dev/null
@@ -0,0 +1,19 @@
+import java.awt.*;
+
+public class ftest {   
+       public static void main(String [] s) {
+               
+//             Frame f = new Frame(s[0]);
+               
+//             f.show();
+               
+//             System.getProperties().list (System.out);
+
+               System.out.println ("-- default toolkit ---");
+               System.out.println (Toolkit.getDefaultToolkit().
+                 getClass().getName() );
+               
+               }
+       }
+       
+       
\ No newline at end of file
diff --git a/tests/hello.java b/tests/hello.java
new file mode 100644 (file)
index 0000000..8243e1b
--- /dev/null
@@ -0,0 +1,5 @@
+public class hello {
+       public static void main(String[] s) {
+               System.out.println ("Hello world");
+               }
+       }
diff --git a/tests/helper.java b/tests/helper.java
new file mode 100644 (file)
index 0000000..4d340a3
--- /dev/null
@@ -0,0 +1,3 @@
+
+public class helper {
+       }
diff --git a/tests/hi.java b/tests/hi.java
new file mode 100644 (file)
index 0000000..ca1c61e
--- /dev/null
@@ -0,0 +1,12 @@
+public class hi {
+   public static void Ausgabe() {
+      System.out.println ("eine Zeile Text");
+   }
+
+   public static void main(String[] args) {
+      int i;
+      for (i=0; i<10; i++) Ausgabe();
+
+      System.out.println ("Juhu, das funktioniert");
+   }
+}
diff --git a/tests/intsieve.java b/tests/intsieve.java
new file mode 100644 (file)
index 0000000..e4c1620
--- /dev/null
@@ -0,0 +1,52 @@
+
+// Primzahlen sieben,  Java-Version
+
+public class intsieve {
+       
+       static void sievenumber(int n, int[] no_prime, int p) {
+               int i;
+               for (i = p*2; i <= n; i += p)
+                       no_prime[i] = 1;
+               }
+                               
+       static void sieving(int n, int[] no_prime) {
+               int p;
+               for (p = 2; p <= n; p++) {
+                       if (no_prime[p] != 0) sievenumber(n, no_prime, p);
+                       }
+               }
+                       
+       static public void main(String [] s) {
+
+               int count=0;
+               int p;
+               
+               int n = Integer.parseInt (s[0]);
+               int times = Integer.parseInt (s[1]);
+                               
+               int no_prime[] = new int[n+1];
+       
+               System.out.print ("Start sieving primes from 2 to ");
+               System.out.print (n);
+               System.out.print (" for ");
+               System.out.print (times);
+               System.out.println (" times");
+               
+               for (; times > 0; times--) {    
+                       for (p = 0; p < n+1; p++)
+                               no_prime[p] = 0;
+                       
+                       sieving(n, no_prime);
+               
+                       count = 0;
+                       for (p = 2; p <= n; p++)
+                               if (no_prime[p] != 0) count++;
+                       }
+                                       
+               System.out.print (".... done, number of primes: ");
+               System.out.println (count);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/jctest.java b/tests/jctest.java
new file mode 100644 (file)
index 0000000..2209385
--- /dev/null
@@ -0,0 +1,1245 @@
+/************************* test/jctest.java ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Eine Klasse zum Testen (fast) aller JavaVM-Instruktionen
+       in verschiedenen Konstellationen.
+
+       Die Ausgabe, die dieses Programm generiert, sollte bei allen
+       verschiedenen Java-Interpreter/Compiler-Systemen gleich
+       sein. Wenn nicht, dann ist wahrscheinlich eines der Systeme
+       fehlerhaft.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/12/03
+
+*******************************************************************************/
+
+
+public class jctest implements jcinterface {
+       static int i1=77;
+       static long l1=123456789,l2=987654321,l3=-99999999999999L;
+       static int i2,i3=-100;
+       static float f1=0.1F,f2=0.2F,f3=0.3F;
+       static double d1=0.001,d2=0.002,d3=0.003;
+       static String s1,s2="der konstante String";
+
+       int n_i1,n_i2,n_i3;
+       long n_l1,n_l2,n_l3,n_l4;
+       float n_f1,n_f2,n_f3,n_f4;
+       int n_i4;
+       double n_d1,n_d2,n_d3,n_d4;
+
+       
+       public static void main(String[] s) {
+               p ("=================== JavaVM - Tester ========================");
+
+               p ("------------------- test arguments");
+               int i;
+               for (i=0; i<s.length; i++) p(s[i]);
+
+               testgeneral();
+               testtables();
+               testcasts();
+               testspecialnullpointers();
+               testarrays();
+               
+               p ("------------------- test consts");
+               testconst ( 1,          1);
+               testconst (-1,         -1);
+               testconst (-24123,     -4918923241323L);
+               testconst (-243511,    -4423423234231423L);
+               testconst (0x7fffffff, 0x7fffffffffffffffL);
+
+               p ("------------------- test ints");
+               testint (1,2);
+               testint (-1,17);
+               testint (-24351,24123);
+               testint (4918923,-441423);
+               testint (0,0);
+               testint (-1,-1);
+               testint (1423487,123444444);
+               testint (0x7fffffff,1);
+               testint (0,0x7fffffff);
+               testint (0x3333,143444);
+               testint (4444441,12342);
+
+               p ("------------------- test longs");
+               testlong (1,2);
+               testlong (-1,17);
+               testlong (-24351,24123);
+               testlong (4918923241323L,-4423423234231423L);
+               testlong (0,0);
+               testlong (-1,-1);
+               testlong (1423487,123444442344L);
+               testlong (0x7fffffffffffffffL,1);
+               testlong (0,0x7fffffffffffffffL);
+               testlong (0x3333,143444);
+               testlong (4444441,12342);
+
+               p ("------------------- test floats");
+               testfloat ((float) 1,(float) 2.042);
+               testfloat ((float) -1.234,(float) 17.44);
+               testfloat ((float) -24351,(float) 24123);
+               testfloat ((float) 0.1,(float) 1243);
+               testfloat ((float) 0.0,(float) -555.4132);
+               testfloat ((float) 77.0,(float) -555);
+               testfloat ((float) 2147483000.0,(float) -555234);
+
+               p ("------------------- test doubles");
+               testdouble (1,2.042);
+               testdouble (-1.234,17.44);
+               testdouble (-24351,24123);
+               testdouble (0.1,1243);
+               testdouble (0.0,-555.4132);
+               testdouble (77.0,-555);
+               testdouble (2147483000.0,-555234);
+               
+
+               p ("=================== end of test =========================");                        
+               }
+
+
+       static /* init */ {
+               p ("successful initialisation");
+               }
+
+
+               
+       public static void testgeneral() {
+               
+               int i;
+               // ******************** basic data types *******************************
+               
+               p ("------------------- test int-PUSH-STORE-LOAD");
+               int j = -1;
+               p(j); p (0); p(2); p(17); p(-100); 
+               p (500); p(-32768); p(-32769); p(32767); p(32768);
+               p (90000); p(-1000000000);
+               
+               p ("------------------- test long-PUSH-STORE-LOAD");
+               long l = 3L;
+               p ( l ); p ( 0L ); p ( 99L );
+               p (500L); p(-32768L); p(-32769L); p(32767L); p(32768L);
+               p ( 6900000000000L ); p ( 349827389478173274L );
+
+               p ("------------------- test float-PUSH-STORE-LOAD");
+               float f = 99.444F;
+               p ( f ); p (0.0F); p (1.0F); p (342323423478.2223434234232334F);
+       
+               p ("------------------- test double-PUSH-STORE-LOAD");
+               double d = 99234.42D;
+               p ( d ); p (0.0D); p (1.0D); p (342323423478.2223434234232334D);
+
+
+               // ******************** static variables *******************************
+
+               p ("------------------- test static variables");        
+               i1 = i1+i2+i3;
+               l2 = l1+l2+l3;
+               f1 = f1*f2;
+               p (i1); p(i2); p(i3); 
+               p (l1); p(l2); p(l3);
+               p (f1); p(f2); p(f3);
+               p (d1); p(d2); p(d3);
+
+               // ******************** arithmetic test ********************************
+               
+               p ("------------------- test arithmetic");
+               i1 = 17;
+               i2 = 0x7fffffff;
+               p (i2);
+               p (i2+1);
+               p (i1-i2);
+               l1 = 0x7fffffffffffffffL;
+               p (l1);
+               p (l1+1);
+               p (l1+0x7fffffffffffffffL);
+               
+               
+               // ******************** test method calls ******************************
+               
+               p ("statische methode");
+               jctest ttt = new jctest ();
+               ttt.p_manyparam (19,18,17,16, 88,77,66,55, 
+                                0.1F,0.2F,0.3F,0.4F, -2.0D,-3.0D,-4.0D,-5.0D );
+               jcinterface ttt2 = ttt;
+               ttt2.p_nonstatic ("interface method");
+
+               }
+
+
+
+       // ************************ test tables ************************************
+               
+       public static void testtables() {
+               int i;
+
+               p ("------------------- test tableswitch");
+
+               for (i = -5; i < 15; i++) {
+                       switch (i) {
+                               case  2:  p ("->  2"); break;   
+                               case  3:  p ("->  3"); break;   
+                               case  5:  p ("->  5"); break;   
+                               case  6:  p ("->  6"); break;
+                               case  7:  p ("->  7"); break;
+                               case  8:  p ("->  8"); break;
+                               case 10:  p ("-> 10"); break;
+                               default:  p ("default"); break;
+                               }
+                       }
+
+               p ("------------------- test lookupswitch");
+
+               for (i = -5; i < 15; i++) {
+                       switch (i) {
+                               case  2:  p ("->  2"); break;
+                               case  8:  p ("->  8"); break;
+                               case 14:  p ("-> 14"); break;
+                               case -4:  p ("-> -4"); break;
+                               default:  p ("default"); break;
+                               }
+                       }       
+               }
+
+
+       // ****************** test type casts and array stores *********************            
+
+       public static void testcasts() {
+               Object    o   = new Object();
+               Object    oi  = new Integer(0);
+               Object[]  oa  = new Object [1];
+               Object[]  oia = new Integer[1];
+               Integer   i   = new Integer(0);
+               Integer[] ia;
+
+               p ("------------------- test casts");
+
+               try {
+                       p ("type cast check: Integer = Object(Integer)");
+                       i = (Integer) oi;
+                       p ("type cast check: Integer = Object");
+                       i = (Integer) o;
+                       p ("error: class cast exception not thrown");
+                       }       
+               catch (ClassCastException c) {
+                       p ("exception: class cast");
+                       }
+
+               try {
+                       p ("type cast check: Integer[] = Object(Integer)[]");
+                       ia = (Integer[]) oia;
+                       p ("type cast check: Integer[] = Object[]");
+                       ia = (Integer[]) oa;
+                       p ("error: class cast exception not thrown");
+                       }       
+               catch (ClassCastException c) {
+                       p ("exception: class cast");
+                       }
+
+               try {
+                       p ("array store check: Object(Integer)[0] = Integer");
+                       oia[0] = i;
+                       p ("array store check: Object(Integer)[0] = Object");
+                       oia[0] = o;
+                       p ("error: array store exception not thrown");
+                       }       
+               catch (ArrayStoreException c) {
+                       p ("exception: array store");
+                       }
+               }
+
+
+       // ****************** test special null pointers ***************************            
+
+       public static void testspecialnullpointers() {
+               int i = 0;
+               jctest c = null;
+               jcinterface f = null;
+
+               p ("------------------- test special null pointers");
+
+               try {
+                       p ("null pointer check: put field");
+                       c.n_i1 = 0;
+                       p ("error: put field null pointer exception not thrown");
+                       }       
+               catch (NullPointerException x) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("null pointer check: get field");
+                       i = c.n_i1;
+                       p ("error: get field null pointer exception not thrown");
+                       }       
+               catch (NullPointerException x) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("null pointer check: invokevirtual");
+                       c.p_nonstatic("invokevirtual");
+                       p ("error: invokevirtual null pointer exception not thrown");
+                       }       
+               catch (NullPointerException x) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("null pointer check: invokeinterface");
+                       f.p_nonstatic("invokeinterface");
+                       p ("error: invokeinterface null pointer exception not thrown");
+                       }       
+               catch (NullPointerException x) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("null pointer check: monitorenter");
+                       synchronized (c) {
+                               p ("error: monitorenter null pointer exception not thrown");
+                               }
+                       }       
+               catch (NullPointerException x) {
+                       p ("exception: null pointer");
+                       }
+               }
+
+
+       // ************************ test array bounds ******************************            
+
+       public static void testarraybounds(byte[] ba, int i) {
+               
+                       p ("testarraybounds: " + (i - 10));
+                       ba[i-10] = 0;
+                       p ("testarraybounds: " + (i - 5));
+                       ba[i-5]  = 0;
+                       p ("testarraybounds: " + (i));
+                       ba[i]    = 0;
+                       p ("testarraybounds: " + (i + 5));
+                       ba[i+5]  = 0;
+                       p ("testarraybounds: " + (i + 10));
+                       ba[i+10] = 0;
+               }
+
+
+       // ************************ test arrays ************************************            
+
+       public static void testarrays() {
+               int    i;
+               long   l;
+               float  f;
+               double d;
+               String s;
+               
+               p ("------------------- test byte arrays");
+
+               byte[] ba = null;
+
+               try {
+                       p ("null pointer check: byte array store");
+                       ba[1] = 0;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: byte array load");
+                       i = ba[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("negative array size check: byte array");
+                       ba = new byte [-2];
+                       p ("error: negative array size exception not thrown");
+                       }       
+               catch (NegativeArraySizeException c) {
+                       p ("exception: negative array size");
+                       }
+
+               ba = new byte [100];
+
+
+               try {
+                       p ("array bound check: byte array store");
+                       ba[-1] = 0;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: byte array load");
+                       i = ba[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               try {
+                       testarraybounds(ba, 5);
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+5);
+                       }
+               try {
+                       testarraybounds(ba, 50);
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+50);
+                       }
+               try {
+                       testarraybounds(ba, 100);
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+100);
+                       }
+
+               try {
+                       ba[-4] = 0;
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-4));
+                       }
+               try {
+                       ba[-3] = 0;
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-3));
+                       }
+               for (i=-2; i<102; i++) { 
+                       try {
+                               ba[i] = (byte) (i-50);
+                               }       
+                       catch (ArrayIndexOutOfBoundsException c) {
+                               p ("exception: out of bounds: "+i);
+                               }
+                       }
+               try {
+                       ba[102] = 0;
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+102);
+                       }
+               try {
+                       ba[103] = 0;
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+103);
+                       }
+               for (i=0; i<100; i++) p (ba[i]);                
+
+
+               p ("-------- test short arrays");               
+
+               short[] sa = null;
+
+               try {
+                       p ("null pointer check: short array store");
+                       sa[1] = 0;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: short array load");
+                       i = sa[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               sa = new short [100];
+
+               try {
+                       p ("array bound check: short array store");
+                       sa[-1] = 0;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: short array load");
+                       i = sa[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               for (i=0; i<100; i++) sa[i] = (short) (i-50);
+               for (i=0; i<100; i++) p (sa[i]);
+               
+
+               p ("-------- test int arrays");         
+
+               int[] ia = null;
+
+               try {
+                       p ("null pointer check: int array store");
+                       ia[1] = 0;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: int array load");
+                       i = ia[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               ia = new int [50];
+
+               try {
+                       p ("array bound check: int array store");
+                       ia[-1] = 0;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: int array load");
+                       i = ia[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               for (i=0; i<10; i++) ia[i] = (123456 + i);
+               for (i=0; i<10; i++) p (ia[i]);
+
+               
+
+               p ("-------- test long arrays");                
+
+               long[] la = null;
+
+               try {
+                       p ("null pointer check: long array store");
+                       la[1] = 0;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: long array load");
+                       l = la[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               la = new long [10];
+
+               try {
+                       p ("array bound check: long array store");
+                       la[-1] = 0;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: long array load");
+                       l = la[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               for (i=0; i<10; i++) la[i] = (1234567890123L + i);
+               for (i=0; i<10; i++) p (la[i]);
+
+               
+               p ("-------- test char arrays");                
+
+               char[] ca = null;
+
+               try {
+                       p ("null pointer check: char array store");
+                       ca[1] = 0;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: char array load");
+                       i = ca[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               ca = new char [50];
+
+               try {
+                       p ("array bound check: char array store");
+                       ca[-1] = 0;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: char array load");
+                       i = ca[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               for (i=0; i<50; i++) ca[i] = (char) ('A' + i);
+               for (i=0; i<50; i++) p (ca[i]);
+
+               p ("-------- test address arrays");
+
+               String[] sta = null;
+
+               try {
+                       p ("null pointer check: address array store");
+                       sta[1] = null;
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+               try {
+                       p ("null pointer check: address array load");
+                       s = sta[1];
+                       p ("error: null pointer exception not thrown");
+                       }       
+               catch (NullPointerException c) {
+                       p ("exception: null pointer");
+                       }
+
+               try {
+                       p ("negative array size check: address array");
+                       sta = new String[-3];
+                       p ("error: negative array size exception not thrown");
+                       }       
+               catch (NegativeArraySizeException c) {
+                       p ("exception: negative array size");
+                       }
+
+               sta = new String[5];
+
+               try {
+                       p ("array bound check: address array store");
+                       sta[-1] = null;
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+               try {
+                       p ("array bound check: address array load");
+                       s = sta[-1];
+                       p ("error: exception not thrown");
+                       }       
+               catch (ArrayIndexOutOfBoundsException c) {
+                       p ("exception: out of bounds: "+(-1));
+                       }
+
+               for (i=0; i<5; i++) sta[i] = Integer.toString(i) + ". Zeile";
+               for (i=0; i<5; i++) p (sta[i]);
+               
+               p ("-------- test multi dimensional arrays");
+
+               int [][][] iaaa = null;
+
+               try {
+                       p ("negative array size check: multi dimensional array");
+                       iaaa = new int[2][3][-4];
+                       p ("error: negative array size exception not thrown");
+                       }       
+               catch (NegativeArraySizeException c) {
+                       p ("exception: negative array size");
+                       }
+
+               iaaa = new int[2][3][4];
+               long [][][] laaa = new long[2][3][6];
+               float [][][] faaa = new float[2][3][4];
+               double [][][] daaa = new double[3][4][7];
+               for (i=0; i<2; i++) {
+                       int i2; for (i2=0; i2<3; i2++) {
+                               int i3; for (i3=0; i3<4; i3++) {
+                                       iaaa[i][i2][i3] = i*i*i + i2*i2 + i3;
+                                       laaa[i][i2][i3] = i*i*i + i2*i2 + i3 + 7;
+                                       faaa[i][i2][i3] = i*i*i + i2*i2 + i3 + 0.4F;
+                                       daaa[i][i2][i3] = i*i*i + i2*i2 + i3 - 47.0001;
+                                       p (iaaa[i][i2][i3]);
+                                       p (laaa[i][i2][i3]);
+                                       p (faaa[i][i2][i3]);
+                                       p (daaa[i][i2][i3]);
+                                       }
+                               }
+                       }
+
+
+                                       
+               }
+
+
+       static public void testconst(int i, long l) {
+               p ("TESTCONST CALLED WITH ", i);
+               p ("                  AND ", l);
+               
+               if (!(i == (0))) p("not IF_ICMPEQ", (0));
+               if (!(i != (0))) p("not IF_ICMPNE", (0));
+               if (!(i <  (0))) p("not IF_ICMPLT", (0));
+               if (!(i <= (0))) p("not IF_ICMPLE", (0));
+               if (!(i >  (0))) p("not IF_ICMPGT", (0));
+               if (!(i >= (0))) p("not IF_ICMPGE", (0));
+
+               if (!(l == (0))) p("not IF_LCMPEQ", (0));
+               if (!(l != (0))) p("not IF_LCMPNE", (0));
+               if (!(l <  (0))) p("not IF_LCMPLT", (0));
+               if (!(l <= (0))) p("not IF_LCMPLE", (0));
+               if (!(l >  (0))) p("not IF_LCMPGT", (0));
+               if (!(l >= (0))) p("not IF_LCMPGE", (0));
+
+               p("IADDCONST:  ", i  +  (-1));
+               p("ISUBCONST:  ", i  -  (-1));
+               p("IMULCONST:  ", i  *  (-1));
+               p("ISHLCONST:  ", i <<  (-1));
+               p("ISHRCONST:  ", i >>  (-1));
+               p("IUSHRCONST: ", i >>> (-1));
+               p("IANDCONST:  ", i  &  (-1));
+               p("IORCONST:   ", i  |  (-1));
+               p("IXORCONST:  ", i  ^  (-1));
+
+               if (!(i == (-1))) p("not IF_ICMPEQ", (-1));
+               if (!(i != (-1))) p("not IF_ICMPNE", (-1));
+               if (!(i <  (-1))) p("not IF_ICMPLT", (-1));
+               if (!(i <= (-1))) p("not IF_ICMPLE", (-1));
+               if (!(i >  (-1))) p("not IF_ICMPGT", (-1));
+               if (!(i >= (-1))) p("not IF_ICMPGE", (-1));
+
+               p("LADDCONST:  ", l  +  (-1));
+               p("LSUBCONST:  ", l  -  (-1));
+               p("LMULCONST:  ", l  *  (-1));
+               p("LSHLCONST:  ", l <<  (-1));
+               p("LSHRCONST:  ", l >>  (-1));
+               p("LUSHRCONST: ", l >>> (-1));
+               p("LANDCONST:  ", l  &  (-1));
+               p("LORCONST:   ", l  |  (-1));
+               p("LXORCONST:  ", l  ^  (-1));
+
+               if (!(l == (-1))) p("not IF_LCMPEQ", (-1));
+               if (!(l != (-1))) p("not IF_LCMPNE", (-1));
+               if (!(l <  (-1))) p("not IF_LCMPLT", (-1));
+               if (!(l <= (-1))) p("not IF_LCMPLE", (-1));
+               if (!(l >  (-1))) p("not IF_LCMPGT", (-1));
+               if (!(l >= (-1))) p("not IF_LCMPGE", (-1));
+
+               p("IADDCONST:  ", i  +  (1));
+               p("ISUBCONST:  ", i  -  (1));
+               p("IMULCONST:  ", i  *  (1));
+               p("ISHLCONST:  ", i <<  (1));
+               p("ISHRCONST:  ", i >>  (1));
+               p("IUSHRCONST: ", i >>> (1));
+               p("IANDCONST:  ", i  &  (1));
+               p("IORCONST:   ", i  |  (1));
+               p("IXORCONST:  ", i  ^  (1));
+
+               if (!(i == (1))) p("not IF_ICMPEQ", (1));
+               if (!(i != (1))) p("not IF_ICMPNE", (1));
+               if (!(i <  (1))) p("not IF_ICMPLT", (1));
+               if (!(i <= (1))) p("not IF_ICMPLE", (1));
+               if (!(i >  (1))) p("not IF_ICMPGT", (1));
+               if (!(i >= (1))) p("not IF_ICMPGE", (1));
+
+               p("LADDCONST:  ", l  +  (1));
+               p("LSUBCONST:  ", l  -  (1));
+               p("LMULCONST:  ", l  *  (1));
+               p("LSHLCONST:  ", l <<  (1));
+               p("LSHRCONST:  ", l >>  (1));
+               p("LUSHRCONST: ", l >>> (1));
+               p("LANDCONST:  ", l  &  (1));
+               p("LORCONST:   ", l  |  (1));
+               p("LXORCONST:  ", l  ^  (1));
+
+               if (!(l == (1))) p("not IF_LCMPEQ", (1));
+               if (!(l != (1))) p("not IF_LCMPNE", (1));
+               if (!(l <  (1))) p("not IF_LCMPLT", (1));
+               if (!(l <= (1))) p("not IF_LCMPLE", (1));
+               if (!(l >  (1))) p("not IF_LCMPGT", (1));
+               if (!(l >= (1))) p("not IF_LCMPGE", (1));
+
+               p("IADDCONST:  ", i  +  (255));
+               p("ISUBCONST:  ", i  -  (255));
+               p("IMULCONST:  ", i  *  (255));
+               p("ISHLCONST:  ", i <<  (255));
+               p("ISHRCONST:  ", i >>  (255));
+               p("IUSHRCONST: ", i >>> (255));
+               p("IANDCONST:  ", i  &  (255));
+               p("IORCONST:   ", i  |  (255));
+               p("IXORCONST:  ", i  ^  (255));
+
+               if (!(i == (255))) p("not IF_ICMPEQ", (255));
+               if (!(i != (255))) p("not IF_ICMPNE", (255));
+               if (!(i <  (255))) p("not IF_ICMPLT", (255));
+               if (!(i <= (255))) p("not IF_ICMPLE", (255));
+               if (!(i >  (255))) p("not IF_ICMPGT", (255));
+               if (!(i >= (255))) p("not IF_ICMPGE", (255));
+
+               p("LADDCONST:  ", l  +  (255));
+               p("LSUBCONST:  ", l  -  (255));
+               p("LMULCONST:  ", l  *  (255));
+               p("LSHLCONST:  ", l <<  (255));
+               p("LSHRCONST:  ", l >>  (255));
+               p("LUSHRCONST: ", l >>> (255));
+               p("LANDCONST:  ", l  &  (255));
+               p("LORCONST:   ", l  |  (255));
+               p("LXORCONST:  ", l  ^  (255));
+
+               if (!(l == (255))) p("not IF_LCMPEQ", (255));
+               if (!(l != (255))) p("not IF_LCMPNE", (255));
+               if (!(l <  (255))) p("not IF_LCMPLT", (255));
+               if (!(l <= (255))) p("not IF_LCMPLE", (255));
+               if (!(l >  (255))) p("not IF_LCMPGT", (255));
+               if (!(l >= (255))) p("not IF_LCMPGE", (255));
+
+               p("IADDCONST:  ", i  +  (256));
+               p("ISUBCONST:  ", i  -  (256));
+               p("IMULCONST:  ", i  *  (256));
+               p("ISHLCONST:  ", i <<  (256));
+               p("ISHRCONST:  ", i >>  (256));
+               p("IUSHRCONST: ", i >>> (256));
+               p("IANDCONST:  ", i  &  (256));
+               p("IORCONST:   ", i  |  (256));
+               p("IXORCONST:  ", i  ^  (256));
+
+               if (!(i == (256))) p("not IF_ICMPEQ", (256));
+               if (!(i != (256))) p("not IF_ICMPNE", (256));
+               if (!(i <  (256))) p("not IF_ICMPLT", (256));
+               if (!(i <= (256))) p("not IF_ICMPLE", (256));
+               if (!(i >  (256))) p("not IF_ICMPGT", (256));
+               if (!(i >= (256))) p("not IF_ICMPGE", (256));
+
+               p("LADDCONST:  ", l  +  (256));
+               p("LSUBCONST:  ", l  -  (256));
+               p("LMULCONST:  ", l  *  (256));
+               p("LSHLCONST:  ", l <<  (256));
+               p("LSHRCONST:  ", l >>  (256));
+               p("LUSHRCONST: ", l >>> (256));
+               p("LANDCONST:  ", l  &  (256));
+               p("LORCONST:   ", l  |  (256));
+               p("LXORCONST:  ", l  ^  (256));
+
+               if (!(l == (256))) p("not IF_LCMPEQ", (256));
+               if (!(l != (256))) p("not IF_LCMPNE", (256));
+               if (!(l <  (256))) p("not IF_LCMPLT", (256));
+               if (!(l <= (256))) p("not IF_LCMPLE", (256));
+               if (!(l >  (256))) p("not IF_LCMPGT", (256));
+               if (!(l >= (256))) p("not IF_LCMPGE", (256));
+
+               p("IADDCONST:  ", i  +  (32767));
+               p("ISUBCONST:  ", i  -  (32767));
+               p("IMULCONST:  ", i  *  (32767));
+               p("ISHLCONST:  ", i <<  (32767));
+               p("ISHRCONST:  ", i >>  (32767));
+               p("IUSHRCONST: ", i >>> (32767));
+               p("IANDCONST:  ", i  &  (32767));
+               p("IORCONST:   ", i  |  (32767));
+               p("IXORCONST:  ", i  ^  (32767));
+
+               if (!(i == (32767))) p("not IF_ICMPEQ", (32767));
+               if (!(i != (32767))) p("not IF_ICMPNE", (32767));
+               if (!(i <  (32767))) p("not IF_ICMPLT", (32767));
+               if (!(i <= (32767))) p("not IF_ICMPLE", (32767));
+               if (!(i >  (32767))) p("not IF_ICMPGT", (32767));
+               if (!(i >= (32767))) p("not IF_ICMPGE", (32767));
+
+               p("LADDCONST:  ", l  +  (32767));
+               p("LSUBCONST:  ", l  -  (32767));
+               p("LMULCONST:  ", l  *  (32767));
+               p("LSHLCONST:  ", l <<  (32767));
+               p("LSHRCONST:  ", l >>  (32767));
+               p("LUSHRCONST: ", l >>> (32767));
+               p("LANDCONST:  ", l  &  (32767));
+               p("LORCONST:   ", l  |  (32767));
+               p("LXORCONST:  ", l  ^  (32767));
+
+               if (!(l == (32767))) p("not IF_LCMPEQ", (32767));
+               if (!(l != (32767))) p("not IF_LCMPNE", (32767));
+               if (!(l <  (32767))) p("not IF_LCMPLT", (32767));
+               if (!(l <= (32767))) p("not IF_LCMPLE", (32767));
+               if (!(l >  (32767))) p("not IF_LCMPGT", (32767));
+               if (!(l >= (32767))) p("not IF_LCMPGE", (32767));
+
+               p("IADDCONST:  ", i  +  (32768));
+               p("ISUBCONST:  ", i  -  (32768));
+               p("IMULCONST:  ", i  *  (32768));
+               p("ISHLCONST:  ", i <<  (32768));
+               p("ISHRCONST:  ", i >>  (32768));
+               p("IUSHRCONST: ", i >>> (32768));
+               p("IANDCONST:  ", i  &  (32768));
+               p("IORCONST:   ", i  |  (32768));
+               p("IXORCONST:  ", i  ^  (32768));
+
+               if (!(i == (32768))) p("not IF_ICMPEQ", (32768));
+               if (!(i != (32768))) p("not IF_ICMPNE", (32768));
+               if (!(i <  (32768))) p("not IF_ICMPLT", (32768));
+               if (!(i <= (32768))) p("not IF_ICMPLE", (32768));
+               if (!(i >  (32768))) p("not IF_ICMPGT", (32768));
+               if (!(i >= (32768))) p("not IF_ICMPGE", (32768));
+
+               p("LADDCONST:  ", l  +  (32768));
+               p("LSUBCONST:  ", l  -  (32768));
+               p("LMULCONST:  ", l  *  (32768));
+               p("LSHLCONST:  ", l <<  (32768));
+               p("LSHRCONST:  ", l >>  (32768));
+               p("LUSHRCONST: ", l >>> (32768));
+               p("LANDCONST:  ", l  &  (32768));
+               p("LORCONST:   ", l  |  (32768));
+               p("LXORCONST:  ", l  ^  (32768));
+
+               if (!(l == (32768))) p("not IF_LCMPEQ", (32768));
+               if (!(l != (32768))) p("not IF_LCMPNE", (32768));
+               if (!(l <  (32768))) p("not IF_LCMPLT", (32768));
+               if (!(l <= (32768))) p("not IF_LCMPLE", (32768));
+               if (!(l >  (32768))) p("not IF_LCMPGT", (32768));
+               if (!(l >= (32768))) p("not IF_LCMPGE", (32768));
+
+               p("IADDCONST:  ", i  +  (-32768));
+               p("ISUBCONST:  ", i  -  (-32768));
+               p("IMULCONST:  ", i  *  (-32768));
+               p("ISHLCONST:  ", i <<  (-32768));
+               p("ISHRCONST:  ", i >>  (-32768));
+               p("IUSHRCONST: ", i >>> (-32768));
+               p("IANDCONST:  ", i  &  (-32768));
+               p("IORCONST:   ", i  |  (-32768));
+               p("IXORCONST:  ", i  ^  (-32768));
+
+               if (!(i == (-32768))) p("not IF_ICMPEQ", (-32768));
+               if (!(i != (-32768))) p("not IF_ICMPNE", (-32768));
+               if (!(i <  (-32768))) p("not IF_ICMPLT", (-32768));
+               if (!(i <= (-32768))) p("not IF_ICMPLE", (-32768));
+               if (!(i >  (-32768))) p("not IF_ICMPGT", (-32768));
+               if (!(i >= (-32768))) p("not IF_ICMPGE", (-32768));
+
+               p("LADDCONST:  ", l  +  (-32768));
+               p("LSUBCONST:  ", l  -  (-32768));
+               p("LMULCONST:  ", l  *  (-32768));
+               p("LSHLCONST:  ", l <<  (-32768));
+               p("LSHRCONST:  ", l >>  (-32768));
+               p("LUSHRCONST: ", l >>> (-32768));
+               p("LANDCONST:  ", l  &  (-32768));
+               p("LORCONST:   ", l  |  (-32768));
+               p("LXORCONST:  ", l  ^  (-32768));
+
+               if (!(l == (-32768))) p("not IF_LCMPEQ", (-32768));
+               if (!(l != (-32768))) p("not IF_LCMPNE", (-32768));
+               if (!(l <  (-32768))) p("not IF_LCMPLT", (-32768));
+               if (!(l <= (-32768))) p("not IF_LCMPLE", (-32768));
+               if (!(l >  (-32768))) p("not IF_LCMPGT", (-32768));
+               if (!(l >= (-32768))) p("not IF_LCMPGE", (-32768));
+
+               p("IADDCONST:  ", i  +  (-32769));
+               p("ISUBCONST:  ", i  -  (-32769));
+               p("IMULCONST:  ", i  *  (-32769));
+               p("ISHLCONST:  ", i <<  (-32769));
+               p("ISHRCONST:  ", i >>  (-32769));
+               p("IUSHRCONST: ", i >>> (-32769));
+               p("IANDCONST:  ", i  &  (-32769));
+               p("IORCONST:   ", i  |  (-32769));
+               p("IXORCONST:  ", i  ^  (-32769));
+
+               if (!(i == (-32769))) p("not IF_ICMPEQ", (-32769));
+               if (!(i != (-32769))) p("not IF_ICMPNE", (-32769));
+               if (!(i <  (-32769))) p("not IF_ICMPLT", (-32769));
+               if (!(i <= (-32769))) p("not IF_ICMPLE", (-32769));
+               if (!(i >  (-32769))) p("not IF_ICMPGT", (-32769));
+               if (!(i >= (-32769))) p("not IF_ICMPGE", (-32769));
+
+               p("LADDCONST:  ", l  +  (-32769));
+               p("LSUBCONST:  ", l  -  (-32769));
+               p("LMULCONST:  ", l  *  (-32769));
+               p("LSHLCONST:  ", l <<  (-32769));
+               p("LSHRCONST:  ", l >>  (-32769));
+               p("LUSHRCONST: ", l >>> (-32769));
+               p("LANDCONST:  ", l  &  (-32769));
+               p("LORCONST:   ", l  |  (-32769));
+               p("LXORCONST:  ", l  ^  (-32769));
+
+               if (!(l == (-32769))) p("not IF_LCMPEQ", (-32769));
+               if (!(l != (-32769))) p("not IF_LCMPNE", (-32769));
+               if (!(l <  (-32769))) p("not IF_LCMPLT", (-32769));
+               if (!(l <= (-32769))) p("not IF_LCMPLE", (-32769));
+               if (!(l >  (-32769))) p("not IF_LCMPGT", (-32769));
+               if (!(l >= (-32769))) p("not IF_LCMPGE", (-32769));
+       }
+
+       static public void testint(int a, int b) {
+               p ("TESTINT CALLED WITH ", a);
+               p ("                AND ", b);
+               
+               p("IADD:  ", a+b);
+               p("ISUB:  ", a-b);
+               p("IMUL:  ", a*b);
+               try { p("IDIV:  ", a/b); } 
+               catch (ArithmeticException e) { p("divison by zero"); }
+               try { p("IREM:  ", a%b); } 
+               catch (ArithmeticException e) { p("divison by zero"); }
+               p("INEG:  ", -a);
+               p("ISHL:  ", a<<b);
+               p("ISHR:  ", a>>b);
+               p("IUSHR: ", a>>>b);
+               p("IAND:  ", a & b);
+               p("IOR:   ", a | b);
+               p("IXOR:  ", a ^ b);
+
+               p("I2L:   ", (long) a);
+               p("I2F:   ", (float) a);
+               p("I2D:   ", (double) a);
+               p("INT2BYTE: ", (byte) a);      
+               p("INT2CHAR: ", (char) a);      
+               p("INT2SHORT: ", (short) a);    
+
+               if (!(a==0)) p("not IFEQ");
+               if (!(a!=0)) p("not IFNE");
+               if (!(a<0))  p("not IFLT");
+               if (!(a<=0)) p("not IFLE");
+               if (!(a>0))  p("not IFGT");
+               if (!(a>=0)) p("not IFGE");
+
+               if (!(a==b)) p("not IF_ICMPEQ");
+               if (!(a!=b)) p("not IF_ICMPNE");
+               if (!(a<b))  p("not IF_ICMPLT");
+               if (!(a<=b)) p("not IF_ICMPLE");
+               if (!(a>b))  p("not IF_ICMPGT");
+               if (!(a>=b)) p("not IF_ICMPGE");
+               
+       }
+
+       static public void testlong(long a, long b) {
+               p ("TESTLONG called with ", a);
+               p ("                 AND ", b);
+               
+               p("LADD:  ", a + b);
+               p("LSUB:  ", a - b);
+               p("LMUL:  ", a * b);
+               try { p("LDIV:  ", a / b); } 
+               catch (ArithmeticException e) { p("divison by zero"); }
+               try { p("LREM:  ", a % b); } 
+               catch (ArithmeticException e) { p("divison by zero"); }
+               p("LNEG:  ", -a);
+               p("LSHL:  ", a << b);
+               p("LSHR:  ", a >> b);
+               p("LUSHR: ", a >>>b);
+               p("LAND:  ", a &  b);
+               p("LOR:   ", a |  b);
+               p("LXOR:  ", a ^  b);
+
+               p("L2I:   ", (int) a);
+               p("L2F:   ", (float) a);
+               p("L2D:   ", (double) a);
+
+               p("LCMP a == b : ", a == b);
+               p("LCMP a != b : ", a != b);
+               p("LCMP a <  b : ", a <  b);
+               p("LCMP a <= b : ", a <= b);
+               p("LCMP a >  b : ", a >  b);
+               p("LCMP a >= b : ", a >= b);
+
+               if ((a==b)) p("not IF_LCMPEQ");
+               if ((a!=b)) p("not IF_LCMPNE");
+               if ((a<b))  p("not IF_LCMPLT");
+               if ((a<=b)) p("not IF_LCMPLE");
+               if ((a>b))  p("not IF_LCMPGT");
+               if ((a>=b)) p("not IF_LCMPGE");
+       }
+
+       static public void testfloat(float a, float b) {
+               p ("TESTFLOAT called with ", a);
+               p ("                  AND ", b);
+               
+               p("FADD:  ", a+b);
+               p("FSUB:  ", a-b);
+               p("FMUL:  ", a*b);
+               p("FDIV:  ", a/b); 
+               p("FREM:  ", a%b);
+               
+               p("F2I:   ", (int) a);
+               p("F2L:   ", (long) a);
+               p("F2D:   ", (double) a);
+
+               if ((a==b)) p("FCMP a=b");
+               if ((a!=b)) p("FCMP a!=b");
+               if ((a<b))  p("FCMP a<b");
+               if ((a<=b)) p("FCMP a<=b");
+               if ((a>b))  p("FCMP a>b");
+               if ((a>=b)) p("FCMP a>=b");
+       }
+
+       static public void testdouble(double a, double b) {
+               p ("TESTDOUBLE called with ", a);
+               p ("                   AND ", b);
+               
+               p("DADD:  ", a+b);
+               p("DSUB:  ", a-b);
+               p("DMUL:  ", a*b);
+               p("DDIV:  ", a/b); 
+               p("DREM:  ", a%b);
+               
+               p("D2I:   ", (int) a);
+               p("D2L:   ", (long) a);
+               p("D2F:   ", (float) a);
+
+               if ((a==b)) p("DCMP a=b");
+               if ((a!=b)) p("DCMP a!=b");
+               if ((a<b))  p("DCMP a<b");
+               if ((a<=b)) p("DCMP a<=b");
+               if ((a>b))  p("DCMP a>b");
+               if ((a>=b)) p("DCMP a>=b");
+       }
+
+
+       // ********************* output methods ****************************
+       
+       public static int linenum = 0;
+       public static void pnl() {
+               System.out.println ();
+               System.out.print (linenum);
+               System.out.print (".    ");
+               linenum++;
+               }
+
+       public static void p(String a) { System.out.print(a); pnl(); }
+       public static void p(boolean a) {System.out.print(a); 
+                                     pnl();  }
+       public static void p(int a) { System.out.print ("int: ");
+                                     System.out.print(a); 
+                                     pnl();  }
+       public static void p(long a) { System.out.print ("long: ");
+                                      System.out.print(a); 
+                                      pnl(); }
+       public static void p(short a) { System.out.print ("short: ");
+                                      System.out.print(a); 
+                                      pnl(); }
+       public static void p(byte a) { System.out.print ("byte: ");
+                                      System.out.print(a); 
+                                      pnl(); }
+       public static void p(char a) { System.out.print ("char: ");
+                                      System.out.print((int)a); 
+                                      pnl(); }
+       public static void p(float a) { System.out.print ("float: ");
+                                       System.out.print ( java.lang.Float.floatToIntBits(a) ); 
+                                       pnl(); }
+       public static void p(double a) { System.out.print ("double: ");
+                                        System.out.print( java.lang.Double.doubleToLongBits(a) ); 
+                                        pnl(); }
+
+       public static void p(String s,boolean i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s,int i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s,byte i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s,char i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s,short i) { 
+               System.out.print(s); p(i);
+               }
+       public static void p(String s,long l) { 
+               System.out.print(s); p(l);
+               }
+       public static void p(String s,float f) { 
+               System.out.print(s); p(f);
+               }
+       public static void p(String s,double d) {
+               System.out.print(s); p(d);
+               }
+
+
+
+
+       // methods for testing interface and method calls
+
+       public void jctest() { p (" <init> wird aktiviert"); };
+       public void p_manyparam (int p_i1,int p_i2,
+                                int p_i3, int p_i4, 
+                                long p_l1,long p_l2,
+                                long p_l3,long p_l4, 
+                                float p_f1, float p_f2, 
+                                float p_f3, float p_f4,
+                                double p_d1, double p_d2,
+                                double p_d3, double p_d4) {
+               n_i1 = p_i1;
+               n_i2 = p_i2;
+               n_i3 = p_i3;
+               n_i4 = p_i4;
+               n_l1 = p_l1;
+               n_l2 = p_l2;
+               n_l3 = p_l3;
+               n_l4 = p_l4;
+               n_f1 = p_f1;
+               n_f2 = p_f2;
+               n_f3 = p_f3;
+               n_f4 = p_f4;
+               n_d1 = p_d1;
+               n_d2 = p_d2;
+               n_d3 = p_d3;
+               n_d4 = p_d4;
+               }
+               
+       public void p_nonstatic (String a) { 
+               p(a); 
+               p(n_i1);
+               p(n_i2);
+               p(n_i3);
+               p(n_i4);
+               p(n_l1);
+               p(n_l2);
+               p(n_l3);
+               p(n_l4);
+               p(n_f1);
+               p(n_f2);
+               p(n_f3);
+               p(n_f4);
+               p(n_d1);
+               p(n_d2);
+               p(n_d3);
+               p(n_d4);
+               
+               }
+
+       }
+       
+       
+interface jcinterface {        
+       public void p_nonstatic (String a);
+       }
+       
+       
diff --git a/tests/leaf.java b/tests/leaf.java
new file mode 100644 (file)
index 0000000..833a226
--- /dev/null
@@ -0,0 +1,13 @@
+
+public class leaf {
+
+       public static int makesum (int a, int b, int c) {
+               return a+b+c;
+       }
+       
+       public static void main (String[] s) {
+               System.out.println (makesum (1,2,3) );          
+               }
+               
+               
+}
diff --git a/tests/longtest.java b/tests/longtest.java
new file mode 100644 (file)
index 0000000..29abf6e
--- /dev/null
@@ -0,0 +1,8 @@
+
+public class longtest {
+       public static void main(String []s) {
+               System.out.print ("juhu: ");
+               System.out.println ( (long) 0x12345678901234L );
+               }
+               
+}
diff --git a/tests/main.java b/tests/main.java
new file mode 100644 (file)
index 0000000..bc253b6
--- /dev/null
@@ -0,0 +1,44 @@
+
+public class main {
+
+       public static void main(String [] s) {
+               System.out.println ("Ausgabe startet");
+               int i;
+               
+               float fa[] = new float[5];
+               for (i=0; i<5; i++) fa[i]=47.20F + (float)i;
+               for (i=0; i<5; i++) System.out.println(fa[i]);
+               
+               double da[] = new double[5];
+               for (i=0; i<5; i++) da[i]=99.40F + (double)i;
+               for (i=0; i<5; i++) System.out.println(da[i]);
+               
+               long la[] = new long[5];
+               for (i=0; i<5; i++) la[i]=11 + i;
+               for (i=0; i<5; i++) System.out.println(la[i]);
+               
+               int ia[] = new int[5];
+               for (i=0; i<5; i++) ia[i]=99 + i;
+               for (i=0; i<5; i++) System.out.println(ia[i]);
+
+               short sa[] = new short[5];
+               for (i=0; i<5; i++) sa[i]=(short)(77 + i);
+               for (i=0; i<5; i++) System.out.println(sa[i]);
+
+               byte ba[] = new byte[5];
+               for (i=0; i<5; i++) ba[i]=(byte)(66 + i);
+               for (i=0; i<5; i++) System.out.println(ba[i]);
+               
+               boolean boa[] = new boolean[5];
+               for (i=0; i<5; i++) boa[i]=(i<2);
+               for (i=0; i<5; i++) System.out.println(boa[i]);
+               
+               char ca[] = new char[5];
+               for (i=0; i<5; i++) ca[i]=(char)('A' + i);
+               for (i=0; i<5; i++) System.out.println(ca[i]);
+               
+               
+               }
+        }
+
+               
\ No newline at end of file
diff --git a/tests/mem.java b/tests/mem.java
new file mode 100644 (file)
index 0000000..627931a
--- /dev/null
@@ -0,0 +1,28 @@
+
+public class mem {
+       public int dummy;
+       
+       public static void main(String[] s) {
+               int i;
+               
+               for (i=0; i<100000000; i++) {
+                       try {
+                               byte[] b = new byte[10000];
+                               b[0]=17;
+                               } 
+                       catch (java.lang.Throwable c) {
+                               System.out.print ("Out of mem after ");
+                               System.out.print (i);
+                               System.out.println (" allocations.");
+                               }
+                       finally {
+                               System.out.println ("OK");
+                               }
+                       }
+               
+               
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/memtest.java b/tests/memtest.java
new file mode 100644 (file)
index 0000000..7f9fab7
--- /dev/null
@@ -0,0 +1,25 @@
+public class memtest {
+       public memtest next;
+       
+       public static memtest t;
+
+       public memtest (memtest n) { next = n; }
+       public memtest () { };
+
+       public static void main (String[] s) {
+               int i;
+
+               t = new memtest(new memtest(new memtest()));
+               char c[][] = new char[100][10];
+               
+               for (i=0; i<100; i++) {
+                       System.out.print (i);
+                       System.out.println (". Objekt angelegt");
+                       memtest m = new memtest();
+                       }       
+       
+               }
+
+       }
+
+       
\ No newline at end of file
diff --git a/tests/n.java b/tests/n.java
new file mode 100644 (file)
index 0000000..e2ea205
--- /dev/null
@@ -0,0 +1,7 @@
+
+public class n implements a {
+       public void do_a () { };
+       public void do_a2 () { };
+       public void do_b () { };
+       }
+       
\ No newline at end of file
diff --git a/tests/nan.java b/tests/nan.java
new file mode 100644 (file)
index 0000000..879614b
--- /dev/null
@@ -0,0 +1,11 @@
+public class nan
+{
+       public static void main(String[] s) {
+               double a,b,c;
+               a = -1;
+               b = 0;
+               c = a/b;
+
+               System.out.println (Long.toString(Double.doubleToLongBits(c)>>>4, 16) );
+               }
+       }
diff --git a/tests/prop.java b/tests/prop.java
new file mode 100644 (file)
index 0000000..549e109
--- /dev/null
@@ -0,0 +1,5 @@
+public class prop {
+       public static void main(String [] s) {
+               System.getProperties().save (System.out, "alle properties:");
+               }
+       }
diff --git a/tests/scribble.java b/tests/scribble.java
new file mode 100644 (file)
index 0000000..21dfac6
--- /dev/null
@@ -0,0 +1,29 @@
+import java.applet.*;
+import java.awt.*;
+
+public class scribble extends Applet {
+   private int last_x=0;
+   private int last_y=0;
+
+
+    public void init()
+    {
+       this.setBackground(Color.white);
+    }
+
+
+    public boolean mouseDown(Event e, int x, int y)
+    {
+       last_x = x; last_y=y; 
+       return true;
+    }
+
+    public boolean mouseDrag(Event e, int x, int y)
+    {
+       Graphics g = getGraphics();
+       g.setColor (Color.black);
+       g.drawLine(last_x,last_y,x,y);
+       last_x=x; last_y=y;
+       return true;
+    }
+}
diff --git a/tests/sieve.java b/tests/sieve.java
new file mode 100644 (file)
index 0000000..cc8cca3
--- /dev/null
@@ -0,0 +1,50 @@
+
+// Primzahlen sieben,  Java-Version
+
+public class sieve {
+       
+       static void sievenumber(int n, boolean[] no_prime, int p) {
+               int i;
+               for (i=p*2; i<=n; i+=p) no_prime[i] = true;
+               }
+                               
+       static void sieving(int n, boolean[] no_prime) {
+               int p;
+               for (p=2; p<=n; p++) {
+                       if (!no_prime[p]) sievenumber(n,no_prime,p);
+                       }
+               }
+                       
+       static public void main(String [] s) {
+
+               int count=0;
+               int p;
+               
+               int n = Integer.parseInt (s[0]);
+               int times = Integer.parseInt (s[1]);
+                               
+               boolean no_prime[] = new boolean[n+1];
+       
+               System.out.print ("Start sieving primes from 2 to ");
+               System.out.print (n);
+               System.out.print (" for ");
+               System.out.print (times);
+               System.out.println (" times");
+               
+               for (; times>0; times--) {      
+                       for (p=0; p<n+1; p++) no_prime[p] = false;
+                       
+                       sieving (n,no_prime);
+               
+                       count=0;
+                       for (p=2; p<=n; p++) if (!no_prime[p]) count++;
+                       
+                       }
+                                       
+               System.out.print (".... done, number of primes: ");
+               System.out.println (count);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/sum.java b/tests/sum.java
new file mode 100644 (file)
index 0000000..a7d5921
--- /dev/null
@@ -0,0 +1,22 @@
+
+// Zahlen summieren, Java Version
+
+public class sum {
+       
+                       
+       static public void main(String [] arg) {
+
+               int s = 0, i = 0;
+               int inc = 1;
+               int n = Integer.parseInt (arg[0]);
+
+               
+               for (i=0; i<n; i+=inc) s+=inc;
+               
+               System.out.print (".... done, sum: ");
+               System.out.println (s);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/sum2.java b/tests/sum2.java
new file mode 100644 (file)
index 0000000..c8f3917
--- /dev/null
@@ -0,0 +1,26 @@
+
+// Zahlen summieren, Java Version
+
+public class sum2 {
+       
+                       
+       static public void main(String [] arg) {
+
+               int s1 = 0, s2 = 0, i = 0;
+               int inc = 1;
+               int n = Integer.parseInt (arg[0]);
+
+               
+               for (i = n; i > 0; i -= inc) {
+                       s1 += inc;
+                       s2 -= inc;
+                       }
+               
+               System.out.print (".... done, sum: ");
+               System.out.println (s1);
+               System.out.println (s2);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/suml.java b/tests/suml.java
new file mode 100644 (file)
index 0000000..00437f8
--- /dev/null
@@ -0,0 +1,25 @@
+
+// Zahlen summieren, Java Version
+
+public class suml {
+       
+                       
+       static public void main(String [] arg) {
+
+               long s1 = 0, s2 = 0;
+               long i = Integer.parseInt (arg[0]);
+
+               
+               for (; i > 0; i--) {
+                       s1++;
+                       s2--;
+                       }
+               
+               System.out.print (".... done, sum: ");
+               System.out.print   (s1);
+               System.out.println (s2);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/sumlempty.java b/tests/sumlempty.java
new file mode 100644 (file)
index 0000000..accf4eb
--- /dev/null
@@ -0,0 +1,21 @@
+
+// Zahlen summieren, Java Version
+
+public class sumlempty {
+       
+                       
+       static public void main(String [] arg) {
+
+               long i = Long.parseLong (arg[0]);
+
+               
+               for (; i > 0; i--) {
+                       }
+               
+               System.out.print (".... done, sum: ");
+               System.out.println (i);
+               }
+               
+               
+       }
+       
\ No newline at end of file
diff --git a/tests/t.java b/tests/t.java
new file mode 100644 (file)
index 0000000..8fa588e
--- /dev/null
@@ -0,0 +1,43 @@
+
+public class t {
+       public static void main(String [] s) {
+               ausgeber m1 = new m(4711);
+               float a=(float)7.5,b=(float)3.2;
+               double ad=5.3,bd=2.1;
+               
+               int i; for (i=0; i<s.length; i++) m1.print (s[i]);
+               
+               m1.print (System.getProperty("file.separator"));
+               m1.print (System.getProperty("line.separator"));
+               
+               m1.print ();
+               System.out.println ((int) ad);
+               m1.print ( (int) (a) );
+               m1.print ( (int) (ad % bd) );
+               m1.print (17.3);
+               m1.print ((float)9.4);
+               m1.print ("bye");
+               }
+        }
+
+class m implements ausgeber { 
+       public int value;
+       
+       public m(int v) { value = v; }
+       
+       public void print(String s) { System.out.println(s); }
+       public void print(int i) { System.out.println(i); }
+       public void print() { System.out.println(value); }
+       public void print(float f) { System.out.println(f); }
+       public void print(double d) { System.out.println(d); }
+       }
+       
+interface ausgeber {
+       public void print(String s);
+       public void print(int i);
+       public void print();
+       public void print(float f);
+       public void print(double d);
+       }
+
+               
\ No newline at end of file
diff --git a/tests/tst.java b/tests/tst.java
new file mode 100644 (file)
index 0000000..5ef9c78
--- /dev/null
@@ -0,0 +1,13 @@
+
+class tst {
+       public static void Main(String[]s) {
+               
+       //      storer ( new char[4][3], new char[2] );
+       }
+       
+
+
+       public static void storer(Object []a, Object o) {
+               a[1] = o;
+       }
+}
diff --git a/tests/x.java b/tests/x.java
new file mode 100644 (file)
index 0000000..5fe7932
--- /dev/null
@@ -0,0 +1,71 @@
+
+import java.io.*;
+
+public class x {
+       static public char[][] text;
+       static public int letters;
+       final static int maxwidth = 200;
+       final static int maxheight = 200;
+
+       static public void main(java.lang.String [] argv) throws 
+           FileNotFoundException, IOException {
+
+               int l,c,width,height;
+               char a;
+               int i;
+               FileInputStream input = new FileInputStream ("x.java");
+               PrintStream output = System.out;
+
+       output.println ("Ausgabe startet");
+               
+               text =  new char[maxheight][maxwidth];
+       output.println ("Feld angelegt");
+       
+               for (l=0; l<maxheight; l++) for (c=0; c<maxwidth; c++) 
+                       text[l][c] = ' ';
+               
+               letters = 0;
+               width = 0;
+               height = 0;
+
+               l=0; c=0;
+               try {
+                while ( (i=input.read()) != -1) {
+                       if (i == '\n') { c=0; l++; }
+                       else {
+                               if (i == '\t') { c = ( (c/4 + 1) * 4); }
+                               else {
+                                       if (c<maxwidth && l<maxheight) {
+                                               a = (char) i;
+                                               text[l][c] = a;
+                                               if (c>=width)  width=c+1;
+                                               if (l>=height) height=l+1;
+                                               }
+                                       c++;
+                                       }
+                               }
+                       }
+               } catch (Throwable e) { };
+               
+           output.println ("------------------------------------------------------");
+
+               for (c=width-1; c>=0; c--) {
+                       for (l=0; l<height; l++) {
+                               if ( (a=text[l][c]) != ' ' ) letters ++;
+                               i = a;
+                               output.write (i);
+                               }
+                       output.println ();
+                       }
+
+               output.println ("------------------------------------------------------");
+               output.println ("Abdruckbare Buchstaben im Text: " + Integer.toString(letters) );
+
+
+               output.flush();
+
+               }
+
+
+       }
+
diff --git a/threads/Makefile b/threads/Makefile
new file mode 100755 (executable)
index 0000000..4e3f217
--- /dev/null
@@ -0,0 +1,27 @@
+
+#######################################################################
+#          Makefile f"ur meine programmunabh"angige Toolbox           #
+#######################################################################
+
+OBJECTS = locks.o thread.o threadio.o
+CC = gcc
+
+ifeq ($(USE_THREADS),YES)
+THREAD_CFLAGS = -DUSE_THREADS -DEXTERNAL_OVERFLOW -DDONT_FREE_FIRST
+else
+THREAD_CFLAGS =
+endif
+
+CFLAGS = $(THREAD_CFLAGS)
+
+threads.a: $(OBJECTS) Makefile sysdep/threads.h
+       rm -f threads.a
+       ar qcs threads.a $(OBJECTS)
+#      ranlib threads.a
+
+locks.o : locks.c
+thread.o : thread.c
+threadio.o : threadio.c
+
+clean: 
+       rm -f *.o *.a
diff --git a/threads/locks.c b/threads/locks.c
new file mode 100644 (file)
index 0000000..f921f47
--- /dev/null
@@ -0,0 +1,576 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * locks.c
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "thread.h"
+#include "locks.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+
+static classinfo *class_java_lang_IllegalMonitorStateException;
+
+#if 1
+#define DBG(s)
+#else
+#define DBG(s)   s
+#endif
+
+extern thread* currentThread;
+
+#if defined(USE_INTERNAL_THREADS)
+
+mutexHashEntry *mutexHashTable;
+int mutexHashTableSize;
+long mutexHashMask;
+
+mutexHashEntry *mutexOverflowTable;
+int mutexOverflowTableSize;
+mutexHashEntry *firstFreeOverflowEntry = 0;
+
+conditionHashEntry *conditionHashTable;
+int conditionHashTableSize;
+long conditionHashMask;
+
+/*
+ * Init the tables.
+ */
+void
+initLocks (void)
+{
+    int i;
+
+    mutexHashTableSize = MUTEX_HASH_TABLE_SIZE;
+    mutexHashTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry) * mutexHashTableSize);
+    mutexHashMask = (mutexHashTableSize - 1) << 3;
+
+    for (i = 0; i < mutexHashTableSize; ++i)
+    {
+               mutexHashTable[i].object = 0;
+               mutexHashTable[i].mutex.holder = 0;
+               mutexHashTable[i].mutex.count = 0;
+               mutexHashTable[i].mutex.muxWaiters = 0;
+               mutexHashTable[i].conditionCount = 0;
+               mutexHashTable[i].next = 0;
+    }
+
+    mutexOverflowTableSize = MUTEX_OVERFLOW_TABLE_SIZE;
+    mutexOverflowTable = (mutexHashEntry*)malloc(sizeof(mutexHashEntry)
+                                                                                                * mutexOverflowTableSize);
+
+    firstFreeOverflowEntry = &mutexOverflowTable[0];
+
+    for (i = 0; i < mutexOverflowTableSize; ++i)
+    {
+               mutexOverflowTable[i].object = 0;
+               mutexOverflowTable[i].mutex.holder = 0;
+               mutexOverflowTable[i].mutex.count = 0;
+               mutexOverflowTable[i].mutex.muxWaiters = 0;
+               mutexOverflowTable[i].conditionCount = 0;
+               mutexOverflowTable[i].next = &mutexOverflowTable[i + 1];
+    }
+    mutexOverflowTable[i - 1].next = 0;
+
+    conditionHashTableSize = CONDITION_HASH_TABLE_SIZE;
+    conditionHashTable = (conditionHashEntry*)malloc(sizeof(conditionHashEntry)
+                                                                                                        * conditionHashTableSize);
+    conditionHashMask = (conditionHashTableSize - 1) << 3;
+
+    for (i = 0; i < conditionHashTableSize; ++i)
+    {
+               conditionHashTable[i].object = 0;
+               conditionHashTable[i].condition.cvWaiters = 0;
+               conditionHashTable[i].condition.mux = 0;
+    }
+
+       /* Load exception classes */
+       class_java_lang_IllegalMonitorStateException =
+               loader_load(unicode_new_char("java/lang/IllegalMonitorStateException"));
+}
+
+/*
+ * Reorders part of the condition hash table. Must be called after an entry has been deleted.
+ */
+void
+reorderConditionHashTable (int begin)
+{
+    while (conditionHashTable[begin].object != 0)
+    {
+       int hashValue = CONDITION_HASH_VALUE(conditionHashTable[begin].object);
+
+       if (hashValue != begin)
+       {
+           while (conditionHashTable[hashValue].object != 0)
+           {
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+               if (hashValue == begin)
+                   break;
+           }
+           if (hashValue != begin)
+           {
+               conditionHashTable[hashValue] = conditionHashTable[begin];
+               conditionHashTable[begin].object = 0;
+               conditionHashTable[begin].condition.cvWaiters = 0;
+               conditionHashTable[begin].condition.mux = 0;
+           }
+       }
+
+       begin = CONDITION_HASH_SUCCESSOR(begin);
+    }
+}
+
+/*
+ * Looks up an entry in the condition hash table.
+ */
+iCv*
+conditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != object
+                  && conditionHashTable[hashValue].object != 0)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    if (conditionHashTable[hashValue].object == 0)
+    {
+               intsRestore();
+               return 0;
+    }
+    
+    intsRestore();
+    return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Adds a new entry in the condition hash table and returns a pointer to the condition
+ */
+iCv*
+addConditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != 0)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    conditionHashTable[hashValue].object = object;
+
+    intsRestore();
+
+    return &conditionHashTable[hashValue].condition;
+}
+
+/*
+ * Removes an entry from the condition hash table.
+ */
+void
+removeConditionForObject (java_objectheader *object)
+{
+    int hashValue;
+
+    intsDisable();
+
+    hashValue = CONDITION_HASH_VALUE(object);
+    while (conditionHashTable[hashValue].object != object)
+               hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
+
+    conditionHashTable[hashValue].object = 0;
+    conditionHashTable[hashValue].condition.cvWaiters = 0;
+    conditionHashTable[hashValue].condition.mux = 0;
+
+    reorderConditionHashTable(CONDITION_HASH_SUCCESSOR(hashValue));
+
+    intsRestore();
+}
+
+/*
+ * Returns the mutex entry for the specified object and increments its conditionCount.
+ */
+mutexHashEntry*
+conditionLockedMutexForObject (java_objectheader *object)
+{
+    int hashValue;
+    mutexHashEntry *entry;
+
+    assert(object != 0);
+
+    intsDisable();
+
+    hashValue = MUTEX_HASH_VALUE(object);
+    entry = &mutexHashTable[hashValue];
+
+    if (entry->object != 0)
+    {
+               if (entry->mutex.count == 0 && entry->conditionCount == 0)
+               {
+                       entry->object = 0;
+                       entry->mutex.holder = 0;
+                       entry->mutex.count = 0;
+                       entry->mutex.muxWaiters = 0;
+               }
+               else
+               {
+                       while (entry->next != 0 && entry->object != object)
+                               entry = entry->next;
+
+                       if (entry->object != object)
+                       {
+                               entry->next = firstFreeOverflowEntry;
+                               firstFreeOverflowEntry = firstFreeOverflowEntry->next;
+                               
+                               entry = entry->next;
+                               entry->object = 0;
+                               entry->next = 0;
+                               assert(entry->conditionCount == 0);
+                       }
+               }
+    }
+
+    if (entry->object == 0)
+        entry->object = object;
+
+    ++entry->conditionCount;
+
+    intsRestore();
+
+    return entry;
+}
+
+/*
+ * Wait for the condition of an object to be signalled
+ */
+void
+wait_cond_for_object (java_objectheader *obj, s8 time)
+{
+    iCv *condition;
+    mutexHashEntry *mutexEntry;
+
+    intsDisable();
+
+    mutexEntry = conditionLockedMutexForObject(obj);
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+
+    internal_wait_cond(&mutexEntry->mutex, condition, time);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+    --mutexEntry->conditionCount;
+
+    intsRestore();
+}
+
+/*
+ * Signal the condition of an object
+ */
+void
+signal_cond_for_object (java_objectheader *obj)
+{
+    iCv *condition;
+
+    intsDisable();
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
+    
+    internal_signal_cond(condition);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+
+    intsRestore();
+}
+
+/*
+ * Broadcast the condition of an object.
+ */
+void
+broadcast_cond_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_broadcast_cond_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Internal: Broadcast the condition of an object.
+ */
+void
+internal_broadcast_cond_for_object (java_objectheader *obj)
+{
+    iCv *condition;
+
+    condition = conditionForObject(obj);
+    if (condition == 0)
+               condition = addConditionForObject(obj);
+
+    internal_broadcast_cond(condition);
+
+    if (condition->cvWaiters == 0 && condition->mux == 0)
+               removeConditionForObject(obj);
+}
+
+/*
+ * Lock a mutex.
+ */
+void
+lock_mutex (iMux *mux)
+{
+       intsDisable();
+       internal_lock_mutex(mux);
+       intsRestore();
+}
+
+/*
+ * Lock the mutex for an object.
+ */
+void
+lock_mutex_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_lock_mutex_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Unlock a mutex.
+ */
+void
+unlock_mutex (iMux *mux)
+{
+       intsDisable();
+       internal_unlock_mutex(mux);
+       intsRestore();
+}
+
+/*
+ * Unlock the mutex for an object.
+ */
+void
+unlock_mutex_for_object (java_objectheader *obj)
+{
+       intsDisable();
+       internal_unlock_mutex_for_object(obj);
+       intsRestore();
+}
+
+/*
+ * Wait on a condition variable.
+ */
+void
+wait_cond (iMux *mux, iCv *cond, s8 timeout)
+{
+       intsDisable();
+       internal_wait_cond(mux, cond, timeout);
+       intsRestore();
+}
+
+/*
+ * Signal a condition variable.
+ */
+void
+signal_cond (iCv *cond)
+{
+       intsDisable();
+       internal_signal_cond(cond);
+       intsRestore();
+}
+
+/*
+ * Broadcast a condition variable.
+ */
+void
+broadcast_cond (iCv *cond)
+{
+       intsDisable();
+       internal_broadcast_cond(cond);
+       intsRestore();
+}
+
+/*
+ * Internal: Lock a mutex.
+ */
+void
+internal_lock_mutex(iMux* mux)
+{
+       assert(blockInts == 1);
+
+    if (mux->holder == 0)
+    {
+               mux->holder = currentThread;
+               mux->count = 1;
+               DBG( fprintf(stderr, "set holder of %p to %p\n", mux, mux->holder); )
+    }
+    else if (mux->holder == currentThread)
+    {
+               mux->count++;
+    }
+    else
+    {
+               while (mux->holder != 0)
+               {
+                       suspendOnQThread(currentThread, &mux->muxWaiters);
+               }
+               mux->holder = currentThread;
+               mux->count = 1;
+    }
+}
+
+/*
+ * Internal: Release a mutex.
+ */
+void
+internal_unlock_mutex(iMux* mux)
+{
+    thread* tid;
+
+       assert(blockInts == 1);
+
+    assert(mux->holder == currentThread);
+    
+    mux->count--;
+    if (mux->count == 0)
+    {
+               mux->holder = 0;
+               if (mux->muxWaiters != 0)
+               {
+                       tid = mux->muxWaiters;
+                       mux->muxWaiters = tid->next;
+                       iresumeThread(tid);
+               }
+    }
+}
+
+/*
+ * Internal: Wait on a conditional variable.
+ *  (timeout currently ignored)
+ */
+void
+internal_wait_cond(iMux* mux, iCv* cv, s8 timeout)
+{
+    int count;
+    thread* tid;
+
+    DBG( fprintf(stderr, "waiting on %p\n", cv); );
+
+    if (mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    count = mux->count;
+    mux->holder = 0;
+    mux->count = 0;
+    cv->mux = mux;
+
+    /* If there's anyone waiting here, wake them up */
+    if (mux->muxWaiters != 0) {
+               tid = mux->muxWaiters;
+               mux->muxWaiters = tid->next;
+               iresumeThread(tid);
+    }
+
+    /* Suspend, and keep suspended until I re-get the lock */
+    suspendOnQThread(currentThread, &cv->cvWaiters);
+    while (mux->holder != 0) {
+               DBG( fprintf(stderr, "woke up\n"); );
+               suspendOnQThread(currentThread, &mux->muxWaiters);
+    }
+
+    mux->holder = currentThread;
+    mux->count = count;
+}
+
+/*
+ * Internal: Wake one thread on a conditional variable.
+ */
+void
+internal_signal_cond (iCv* cv)
+{
+    thread* tid;
+
+    DBG( fprintf(stderr, "signalling on %p\n", cv); );
+
+    /* If 'mux' isn't set then we've never waited on this object. */
+    if (cv->mux == 0) {
+               return;
+    }
+
+    if (cv->mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    /* Remove one thread from cv list */
+    if (cv->cvWaiters != 0) {
+               DBG( fprintf(stderr, "releasing a waiter\n"); );
+
+               tid = cv->cvWaiters;
+               cv->cvWaiters = tid->next;
+
+               /* Place it on mux list */
+               tid->next = cv->mux->muxWaiters;
+               cv->mux->muxWaiters = tid;
+    }
+}
+
+/*
+ * Internal: Wake all threads on a conditional variable.
+ */
+void
+internal_broadcast_cond (iCv* cv)
+{
+    thread** tidp;
+
+    /* If 'mux' isn't set then we've never waited on this object. */
+    if (cv->mux == 0) {
+               return;
+    }
+
+    if (cv->mux->holder != currentThread) {
+               exceptionptr = native_new_and_init(class_java_lang_IllegalMonitorStateException);
+    }
+
+       assert(blockInts == 1);
+
+    /* Find the end of the cv list */
+    if (cv->cvWaiters) {
+               for (tidp = &cv->cvWaiters; *tidp != 0; tidp = &(*tidp)->next)
+                       ;
+
+               /* Place entire cv list on mux list */
+               (*tidp) = cv->mux->muxWaiters;
+               cv->mux->muxWaiters = cv->cvWaiters;
+               cv->cvWaiters = 0;
+    }
+}
+
+#endif
diff --git a/threads/locks.h b/threads/locks.h
new file mode 100644 (file)
index 0000000..e522467
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * locks.h
+ * Manage locking system
+ * This include the mutex's and cv's.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __locks_h
+#define __locks_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+#include "sysdep/defines.h"
+
+#define        WAITFOREVER     -1
+
+#if defined(USE_INTERNAL_THREADS)
+
+struct _thread;
+
+typedef struct _iMux {
+    struct _thread *holder;
+    int        count;
+    struct _thread *muxWaiters;
+} iMux;
+
+typedef struct _iCv {
+       struct _thread*         cvWaiters;
+       struct _iMux*           mux;
+} iCv;
+
+#define MAX_MUTEXES             256
+
+typedef struct _mutexHashEntry
+{
+    java_objectheader *object;
+    iMux mutex;
+    struct _mutexHashEntry *next;
+    int conditionCount;
+} mutexHashEntry;
+
+#define MUTEX_HASH_TRASH_BITS                3
+#define MUTEX_HASH_SIGN_BITS                10
+
+#define MUTEX_HASH_TABLE_SIZE             1024
+#define MUTEX_OVERFLOW_TABLE_SIZE         1024
+/*
+#define MAX_MUTEX_HASH_TABLE_SIZE        65536
+*/
+
+/*
+#define MUTEX_USE_THRESHOLD               1024
+*/
+
+extern long mutexHashMask;
+extern int mutexHashTableSize;
+extern mutexHashEntry *mutexHashTable;
+
+extern mutexHashEntry *mutexOverflowTable;
+extern int mutexOverflowTableSize;
+extern mutexHashEntry *firstFreeOverflowEntry;
+
+#define MUTEX_HASH_MASK                  ((MUTEX_HASH_TABLE_SIZE - 1) << 3)
+
+#if 0
+#define MUTEX_HASH_VALUE(a)      ((((long)(a)) & MUTEX_HASH_MASK) >> MUTEX_HASH_TRASH_BITS)
+#else
+#define MUTEX_HASH_VALUE(a)      (( (((long)(a)) ^ ((long)(a) >> MUTEX_HASH_SIGN_BITS)) & mutexHashMask) >> MUTEX_HASH_TRASH_BITS)
+#endif
+#define MUTEX_HASH_SUCCESSOR(h)                  (((h) + 7) & (mutexHashTableSize - 1))
+
+typedef struct _conditionHashEntry
+{
+    java_objectheader *object;
+    iCv condition;
+} conditionHashEntry;
+
+#define CONDITION_HASH_TABLE_SIZE                1024
+
+#define CONDITION_HASH_VALUE(a)                  ((((long)(a)) & conditionHashMask) >> 3)
+#define CONDITION_HASH_SUCCESSOR(h)              (((h) + 7) & (conditionHashTableSize - 1))
+
+typedef struct
+{
+    bool free;
+    java_objectheader *object;
+    iMux mutex;
+    iCv condition;
+} object_mutex;
+
+extern void initLocks (void);
+
+mutexHashEntry* conditionLockedMutexForObject (java_objectheader *object);
+
+void reorderConditionHashTable (int begin);
+iCv* conditionForObject (java_objectheader *object);
+iCv* addConditionForObject (java_objectheader *object);
+void removeConditionForObject (java_objectheader *object);
+
+/*
+ * use these functions only outside critical sections (intsEnable/intsRestore).
+ */
+
+void signal_cond_for_object (java_objectheader *obj);
+void broadcast_cond_for_object (java_objectheader *obj);
+void wait_cond_for_object (java_objectheader *obj, s8 time);
+void lock_mutex_for_object (java_objectheader *obj);
+void unlock_mutex_for_object (java_objectheader *obj);
+
+void lock_mutex (iMux*);
+void unlock_mutex (iMux*);
+void wait_cond (iMux*, iCv*, s8);
+void signal_cond (iCv*);
+void broadcast_cond (iCv*);
+
+/*
+ * use these internal functions only in critical sections. blockInts must be exactly
+ * 1.
+ */
+void internal_lock_mutex (iMux*);
+void internal_unlock_mutex (iMux*);
+void internal_wait_cond (iMux*, iCv*, s8);
+void internal_signal_cond (iCv*);
+void internal_broadcast_cond (iCv*);
+
+void internal_lock_mutex_for_object (java_objectheader *obj);
+void internal_unlock_mutex_for_object (java_objectheader *obj);
+void internal_broadcast_cond_for_object (java_objectheader *obj);
+
+#endif
+
+#endif /* USE_THREADS */
+
+#endif /* __locks_h */
diff --git a/threads/notyet.c b/threads/notyet.c
new file mode 100644 (file)
index 0000000..3a4535c
--- /dev/null
@@ -0,0 +1,110 @@
+/* ------------------------ thread.c -------------------------- */
+
+/*
+ * Put a thread to sleep.
+ */
+void
+sleepThread(int64 time)
+{
+    thread** tidp;
+
+    /* Sleep for no time */
+    if (time == 0) {
+       return;
+    }
+    
+    intsDisable();
+
+    /* Get absolute time */
+    currentThread->PrivateInfo->time = time + currentTime();
+
+    /* Find place in alarm list */
+    for (tidp = &alarmList; (*tidp) != 0; tidp = &(*tidp)->next) {
+       if ((*tidp)->PrivateInfo->time > currentThread->PrivateInfo->time) {
+           break;
+       }
+    }
+
+    /* If I'm head of alarm list, restart alarm */
+    if (tidp == &alarmList) {
+       MALARM(time);
+    }
+    
+    /* Suspend thread on it */
+    suspendOnQThread(currentThread, tidp);
+    
+    intsRestore();
+}
+
+/*
+ * Handle alarm.
+ * This routine uses a different meaning of "blockInts". Formerly, it was just
+ * "don't reschedule if you don't have to". Now it is "don't do ANY
+ * rescheduling actions due to an expired timer". An alternative would be to
+ * block SIGALARM during critical sections (by means of sigprocmask). But
+ * this would be required quite often (for every outmost intsDisable(),
+ * intsRestore()) and therefore would be much more expensive than just
+ * setting an int flag which - sometimes - might cause an additional
+ * setitimer call.
+ */
+static
+void
+alarmException(int sig)
+{
+    thread* tid;
+    int64 time;
+
+    /* Re-enable signal - necessary for SysV */
+    signal(sig, (SIG_T)alarmException);
+
+    /*
+     * If ints are blocked, this might indicate an inconsistent state of
+     * one of the thread queues (either alarmList or threadQhead/tail).
+     * We better don't touch one of them in this case and come back later.
+     */
+    if (blockInts > 0) {
+       MALARM(50);
+       return;
+    }
+
+    intsDisable();
+
+    /* Wake all the threads which need waking */
+    time = currentTime();
+    while (alarmList != 0 && alarmList->PrivateInfo->time <= time) {
+       tid = alarmList;
+       alarmList = alarmList->next;
+       iresumeThread(tid);
+    }
+
+    /* Restart alarm */
+    if (alarmList != 0) {
+       MALARM(alarmList->PrivateInfo->time - time);
+    }
+
+    /*
+     * The next bit is rather tricky.  If we don't reschedule then things
+     * are fine, we exit this handler and everything continues correctly.
+     * On the otherhand, if we do reschedule, we will schedule the new
+     * thread with alarms blocked which is wrong.  However, we cannot
+     * unblock them here incase we have just set an alarm which goes
+     * off before the reschedule takes place (and we enter this routine
+     * recusively which isn't good).  So, we set a flag indicating alarms
+     * are blocked, and allow the rescheduler to unblock the alarm signal
+     * after the context switch has been made.  At this point it's safe.
+     */
+    alarmBlocked = true;
+    intsRestore();
+    alarmBlocked = false;
+}
+
+/*
+ * How many stack frames have I invoked?
+ */
+long
+framesThread(thread* tid)
+{
+    long count;
+    THREADFRAMES(tid, count);
+    return (count);
+}
diff --git a/threads/thread.c b/threads/thread.c
new file mode 100644 (file)
index 0000000..89dde1d
--- /dev/null
@@ -0,0 +1,681 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * thread.c
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/mman.h>                   /* for mprotect */
+#include <unistd.h>
+
+#include "thread.h"
+#include "locks.h"
+#include "sysdep/defines.h"
+#include "sysdep/threads.h"
+
+#include "../tables.h"
+#include "../native.h"
+#include "../loader.h"
+#include "../builtin.h"
+#include "../asmpart.h"
+
+static classinfo *class_java_lang_ThreadDeath;
+
+#if 1
+#define DBG(s)
+#define SDBG(s)
+#else
+#define DBG(s)                 s
+#define SDBG(s)                s
+#endif
+
+#if defined(USE_INTERNAL_THREADS)
+
+thread* currentThread;
+thread* threadQhead[MAX_THREAD_PRIO + 1];
+thread* threadQtail[MAX_THREAD_PRIO + 1];
+
+thread* liveThreads;
+thread* alarmList;
+
+thread* gcDaemonThread;
+
+int blockInts;
+bool needReschedule;
+
+ctx contexts[MAXTHREADS];
+
+/* Number of threads alive, also counting daemons */
+static int talive;
+
+/* Number of daemon threads alive */
+static int tdaemon;
+
+static void firstStartThread(void);
+
+void reschedule(void);
+
+/* Setup default thread stack size - this can be overwritten if required */
+int threadStackSize = THREADSTACKSIZE;
+
+static thread* startDaemon(void* func, char* nm, int stackSize);
+
+/*
+ * Allocate the stack for a thread
+ */
+void
+allocThreadStack (thread *tid, int size)
+{
+    int pageSize = getpagesize(),
+               result;
+    unsigned long pageBegin;
+
+    CONTEXT(tid).stackMem = malloc(size + 2 * pageSize);
+    assert(CONTEXT(tid).stackMem != 0);
+    CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
+    
+    pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+    pageBegin = pageBegin - pageBegin % pageSize;
+
+    result = mprotect((void*)pageBegin, pageSize, PROT_NONE);
+    assert(result == 0);
+
+    CONTEXT(tid).stackBase = (u1*)pageBegin + pageSize;
+}
+
+/*
+ * Free the stack for a thread
+ */
+void
+freeThreadStack (thread *tid)
+{
+    if (!(CONTEXT(tid).flags & THREAD_FLAGS_NOSTACKALLOC))
+    {
+               int pageSize = getpagesize(),
+                       result;
+               unsigned long pageBegin;
+
+               pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
+               pageBegin = pageBegin - pageBegin % pageSize;
+       
+               result = mprotect((void*)pageBegin, pageSize,
+                                                 PROT_READ | PROT_WRITE | PROT_EXEC);
+               assert(result == 0);
+
+               free(CONTEXT(tid).stackMem);
+    }
+    CONTEXT(tid).stackMem = 0;
+    CONTEXT(tid).stackBase = 0;
+    CONTEXT(tid).stackEnd = 0;
+}
+
+/*
+ * Initialize threads.
+ */
+void
+initThreads(u1 *stackbottom)
+{
+    int i;
+
+    initLocks();
+
+    for (i = 0; i < MAXTHREADS; ++i)
+               contexts[i].free = true;
+
+    /* Allocate a thread to be the main thread */
+    currentThread = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+    assert(currentThread != 0);
+    
+    currentThread->PrivateInfo = 1;
+    CONTEXT(currentThread).free = false;
+
+    liveThreads = currentThread;
+
+    currentThread->name = javastring_new(unicode_new_char("main"));
+    currentThread->priority = NORM_THREAD_PRIO;
+    CONTEXT(currentThread).priority = (u1)currentThread->priority;
+    CONTEXT(currentThread).exceptionptr = 0;
+    currentThread->next = 0;
+    CONTEXT(currentThread).status = THREAD_SUSPENDED;
+    CONTEXT(currentThread).stackBase = CONTEXT(currentThread).stackEnd = stackbottom;
+    THREADINFO(&CONTEXT(currentThread));
+
+    DBG( printf("main thread %p base %p end %p\n", 
+                               currentThread, 
+                               CONTEXT(currentThread).stackBase, 
+                               CONTEXT(currentThread).stackEnd); );
+
+       CONTEXT(currentThread).flags = THREAD_FLAGS_NOSTACKALLOC;
+       CONTEXT(currentThread).nextlive = 0;
+       currentThread->single_step = 0;
+       currentThread->daemon = 0;
+       currentThread->stillborn = 0;
+       currentThread->target = 0;
+       currentThread->interruptRequested = 0;
+       currentThread->group =
+               (threadGroup*)builtin_new(loader_load(unicode_new_char("java/lang/ThreadGroup")));
+       /* we should call the constructor */
+       assert(currentThread->group != 0);
+
+       talive++;
+
+       /* Add thread into runQ */
+       iresumeThread(currentThread);
+
+       /* Start garbage collection thread */
+       gcDaemonThread = startDaemon(gc_thread, "gc", 1024*512);
+       iresumeThread(gcDaemonThread);
+
+       heap_addreference((void**)&gcDaemonThread);
+
+       /* Load exception classes */
+       class_java_lang_ThreadDeath = loader_load(unicode_new_char("java/lang/ThreadDeath"));
+
+       DBG( fprintf(stderr, "finishing initThreads\n"); );
+
+       assert(blockInts == 0);
+}
+
+/*
+ * Start a new thread running.
+ */
+void
+startThread (thread* tid)
+{
+    int i;
+
+    /* Allocate a stack context */
+    for (i = 0; i < MAXTHREADS; ++i)
+               if (contexts[i].free)
+                       break;
+
+    if (i == MAXTHREADS)
+               panic("Too many threads");
+
+    tid->PrivateInfo = i + 1;
+    CONTEXT(tid).free = false;
+    CONTEXT(tid).nextlive = liveThreads;
+    liveThreads = tid;
+    allocThreadStack(tid, threadStackSize);
+    CONTEXT(tid).usedStackTop = CONTEXT(tid).stackBase;
+    CONTEXT(tid).flags = THREAD_FLAGS_GENERAL;
+    CONTEXT(tid).status = THREAD_SUSPENDED;
+    CONTEXT(tid).priority = (u1)tid->priority;
+    CONTEXT(tid).exceptionptr = 0;
+
+    /* Construct the initial restore point. */
+    THREADINIT((&CONTEXT(tid)), firstStartThread);
+
+    DBG( printf("new thread %p base %p end %p\n",
+                               tid, CONTEXT(tid).stackBase,
+                               CONTEXT(tid).stackEnd); );
+
+       talive++;
+       if (tid->daemon)
+               tdaemon++;
+
+       /* Add thread into runQ */
+       iresumeThread(tid);
+}
+
+/*
+ * Start a daemon thread.
+ */
+static thread*
+startDaemon(void* func, char* nm, int stackSize)
+{
+    thread* tid;
+    int i;
+
+    DBG( printf("startDaemon %s\n", nm); );
+
+       tid = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+       assert(tid != 0);
+
+       for (i = 0; i < MAXTHREADS; ++i)
+               if (contexts[i].free)
+                       break;
+       if (i == MAXTHREADS)
+               panic("Too many threads");
+
+       tid->PrivateInfo = i + 1;
+       CONTEXT(tid).free = false;
+       tid->name = 0;          /* for the moment */
+       tid->priority = MAX_THREAD_PRIO;
+       CONTEXT(tid).priority = (u1)tid->priority;
+       tid->next = 0;
+       CONTEXT(tid).status = THREAD_SUSPENDED;
+
+       allocThreadStack(tid, stackSize);
+       tid->single_step = 0;
+       tid->daemon = 1;
+       tid->stillborn = 0;
+       tid->target = 0;
+       tid->interruptRequested = 0;
+       tid->group = 0;
+
+       /* Construct the initial restore point. */
+       THREADINIT((&CONTEXT(tid)), func);
+
+       talive++;
+       tdaemon++;
+
+       return tid;
+}
+
+/*
+ * All threads start here.
+ */
+static void
+firstStartThread(void)
+{
+    methodinfo *method;
+
+    DBG( printf("firstStartThread %p\n", currentThread); );
+
+       /* Every thread starts with the interrupts off */
+       intsRestore();
+       assert(blockInts == 0);
+
+       /* Find the run()V method and call it */
+       method = class_findmethod(currentThread->header.vftbl->class,
+                                                         unicode_new_char("run"), unicode_new_char("()V"));
+       if (method == 0)
+               panic("Cannot find method \'void run ()\'");
+       asm_calljavamethod(method, currentThread, NULL, NULL, NULL);
+
+       killThread(0);
+       assert("Thread returned from killThread" == 0);
+}
+
+/*
+ * Resume a thread running.
+ * This routine has to be called only from locations which ensure
+ * run / block queue consistency. There is no check for illegal resume
+ * conditions (like explicitly resuming an IO blocked thread). There also
+ * is no update of any blocking queue. Both has to be done by the caller
+ */
+void
+iresumeThread(thread* tid)
+{
+    DBG( printf("resumeThread %p\n", tid); );
+
+       intsDisable();
+
+       if (CONTEXT(tid).status != THREAD_RUNNING)
+       {
+               CONTEXT(tid).status = THREAD_RUNNING;
+
+               DBG( fprintf(stderr, "prio is %d\n", CONTEXT(tid).priority); );
+
+               /* Place thread on the end of its queue */
+               if (threadQhead[CONTEXT(tid).priority] == 0) {
+                       threadQhead[CONTEXT(tid).priority] = tid;
+                       threadQtail[CONTEXT(tid).priority] = tid;
+                       if (CONTEXT(tid).priority
+                               > CONTEXT(currentThread).priority)
+                               needReschedule = true;
+               }
+               else
+               {
+                       threadQtail[CONTEXT(tid).priority]->next = tid;
+                       threadQtail[CONTEXT(tid).priority] = tid;
+               }
+               tid->next = 0;
+       }
+       SDBG( else { printf("Re-resuming %p\n", tid); } );
+
+       intsRestore();
+}
+
+/*
+ * Yield process to another thread of equal priority.
+ */
+void
+yieldThread()
+{
+    intsDisable();
+
+    if (threadQhead[CONTEXT(currentThread).priority]
+               != threadQtail[CONTEXT(currentThread).priority])
+    {
+               /* Get the next thread and move me to the end */
+               threadQhead[CONTEXT(currentThread).priority] = currentThread->next;
+               threadQtail[CONTEXT(currentThread).priority]->next = currentThread;
+               threadQtail[CONTEXT(currentThread).priority] = currentThread;
+               currentThread->next = 0;
+               needReschedule = true;
+    }
+
+    intsRestore();
+}
+
+/*
+ * Explicit request by user to resume a thread
+ * The definition says that it is just legal to call this after a preceeding
+ * suspend (which got through). If the thread was blocked for some other
+ * reason (either sleep or IO or a muxSem), we simply can't do it
+ * We use a new thread flag THREAD_FLAGS_USER_SUSPEND for this purpose
+ * (which is set by suspendThread(.))
+ */
+void
+resumeThread(thread* tid)
+{
+    if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
+    {
+               intsDisable();
+               CONTEXT(tid).flags &= ~THREAD_FLAGS_USER_SUSPEND;
+               iresumeThread(tid);
+               intsRestore();
+    }
+}
+
+/*
+ * Suspend a thread.
+ * This is an explicit user request to suspend the thread - the counterpart
+ * for resumeThreadRequest(.). It is JUST called by the java method
+ * Thread.suspend()
+ * What makes it distinct is the fact that the suspended thread is not contained
+ * in any block queue. Without a special flag (indicating the user suspend), we
+ * can't check s suspended thread for this condition afterwards (which is
+ * required by resumeThreadRequest()). The new thread flag
+ * THREAD_FLAGS_USER_SUSPEND is used for this purpose.
+ */
+void
+suspendThread(thread* tid)
+{
+    thread** ntid;
+
+    intsDisable();
+
+    if (CONTEXT(tid).status != THREAD_SUSPENDED)
+    {
+               CONTEXT(tid).status = THREAD_SUSPENDED;
+               
+               /*
+                * This is used to indicate the explicit suspend condition
+                * required by resumeThreadRequest()
+                */
+               CONTEXT(tid).flags |= THREAD_FLAGS_USER_SUSPEND;
+
+               for (ntid = &threadQhead[CONTEXT(tid).priority];
+                        *ntid != 0;
+                        ntid = &(*ntid)->next)
+               {
+                       if (*ntid == tid)
+                       {
+                               *ntid = tid->next;
+                               tid->next = 0;
+                               if (tid == currentThread)
+                               {
+                                       reschedule();
+                               }
+                               break;
+                       }
+               }
+    }
+       SDBG( else { printf("Re-suspending %p\n", tid); } );
+
+       intsRestore();
+}
+
+/*
+ * Suspend a thread on a queue.
+ */
+void
+suspendOnQThread(thread* tid, thread** queue)
+{
+    thread** ntid;
+
+       DBG( printf("suspendOnQThread %p %p\n", tid, queue); );
+
+       assert(blockInts == 1);
+
+       if (CONTEXT(tid).status != THREAD_SUSPENDED)
+       {
+               CONTEXT(tid).status = THREAD_SUSPENDED;
+
+               for (ntid = &threadQhead[CONTEXT(tid).priority];
+                        *ntid != 0;
+                        ntid = &(*ntid)->next)
+               {
+                       if (*ntid == tid)
+                       {
+                               *ntid = tid->next;
+                               /* Insert onto head of lock wait Q */
+                               tid->next = *queue;
+                               *queue = tid;
+                               if (tid == currentThread)
+                               {
+                                       DBG( fprintf(stderr, "suspending %p (cur=%p) with prio %d\n",
+                                                                tid, currentThread, CONTEXT(tid).priority); );
+                                       reschedule();
+                               }
+                               break;
+                       }
+               }
+       }
+       SDBG( else { printf("Re-suspending %p on %p\n", tid, *queue); } );
+}
+
+/*
+ * Kill thread.
+ */
+void
+killThread(thread* tid)
+{
+    thread** ntid;
+
+    intsDisable();
+
+    /* A null tid means the current thread */
+    if (tid == 0)
+    {
+               tid = currentThread;
+    }
+
+       DBG( printf("killThread %p\n", tid); );
+
+       if (CONTEXT(tid).status != THREAD_DEAD)
+       {
+               /* Get thread off runq (if it needs it) */
+               if (CONTEXT(tid).status == THREAD_RUNNING)
+               {
+                       for (ntid = &threadQhead[CONTEXT(tid).priority];
+                                *ntid != 0;
+                                ntid = &(*ntid)->next)
+                       {
+                               if (*ntid == tid)
+                               {
+                                       *ntid = tid->next;
+                                       break;
+                               }
+                       }
+               }
+
+               CONTEXT(tid).status = THREAD_DEAD;
+               talive--;
+               if (tid->daemon) {
+                       tdaemon--;
+               }
+
+               /* If we only have daemons left, then everyone is dead. */
+               if (talive == tdaemon) {
+                       /* Am I suppose to close things down nicely ?? */
+                       exit(0);
+               }
+
+               /* Notify on the object just in case anyone is waiting */
+               internal_lock_mutex_for_object(&tid->header);
+               internal_broadcast_cond_for_object(&tid->header);
+               internal_unlock_mutex_for_object(&tid->header);
+
+               /* Remove thread from live list to it can be garbaged */
+               for (ntid = &liveThreads;
+                        *ntid != 0;
+                        ntid = &(CONTEXT((*ntid)).nextlive))
+               {
+                       if (tid == (*ntid))
+                       {
+                               (*ntid) = CONTEXT(tid).nextlive;
+                               break;
+                       }
+               }
+
+               /* Free stack */
+               freeThreadStack(tid);
+
+               /* free context */
+               CONTEXT(tid).free = true;
+
+               /* Run something else */
+               needReschedule = true;
+       }
+       intsRestore();
+}
+
+/*
+ * Change thread priority.
+ */
+void
+setPriorityThread(thread* tid, int prio)
+{
+    thread** ntid;
+
+    if (tid->PrivateInfo == 0) {
+               tid->priority = prio;
+               return;
+    }
+
+    if (CONTEXT(tid).status == THREAD_SUSPENDED) {
+               CONTEXT(tid).priority = (u8)prio;
+               return;
+    }
+
+    intsDisable();
+
+    /* Remove from current thread list */
+    for (ntid = &threadQhead[CONTEXT(tid).priority]; *ntid != 0; ntid = &(*ntid)->next) {
+               if (*ntid == tid) {
+                       *ntid = tid->next;
+                       break;
+               }
+    }
+
+    /* Insert onto a new one */
+    tid->priority = prio;
+    CONTEXT(tid).priority = (u8)tid->priority;
+    if (threadQhead[prio] == 0) {
+               threadQhead[prio] = tid;
+               threadQtail[prio] = tid;
+               if (prio > CONTEXT(currentThread).priority) {
+                       needReschedule = true;
+               }
+    }
+    else {
+               threadQtail[prio]->next = tid;
+               threadQtail[prio] = tid;
+    }
+    tid->next = 0;
+
+    intsRestore();
+}
+
+/*
+ * Is this thread alive?
+ */
+bool
+aliveThread(thread* tid)
+{
+    if (tid->PrivateInfo != 0 && CONTEXT(tid).status != THREAD_DEAD)
+               return (true);
+    else
+               return (false);
+}
+
+/*
+ * Reschedule the thread.
+ * Called whenever a change in the running thread is required.
+ */
+void
+reschedule(void)
+{
+    int i;
+    thread* lastThread;
+    int b;
+    /*    sigset_t nsig; */
+
+    /* A reschedule in a non-blocked context is half way to hell */
+    assert(blockInts > 0);
+    b = blockInts;
+    
+    /* Check events - we may release a high priority thread */
+    /* Just check IO, no need for a reschedule call by checkEvents() */
+    needReschedule = false;
+    checkEvents(false);
+
+    for (;;)
+    {
+               for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--)
+               {
+                       if (threadQhead[i] != 0)
+                       {
+                               DBG( fprintf(stderr, "found thread %p in head %d\n", threadQhead[i], i); );
+
+                               if (threadQhead[i] != currentThread)
+                               {
+                                       USEDSTACKTOP((CONTEXT(currentThread).usedStackTop));
+
+                                       lastThread = currentThread;
+                                       currentThread = threadQhead[i];
+
+                                       CONTEXT(currentThread).exceptionptr = exceptionptr;
+
+                                       THREADSWITCH((&CONTEXT(currentThread)),
+                                                                (&CONTEXT(lastThread)));
+                                       blockInts = b;
+
+                                       exceptionptr = CONTEXT(currentThread).exceptionptr;
+
+                                       /* Alarm signal may be blocked - if so
+                                        * unblock it.
+                                        */
+                                       /*
+                                         if (alarmBlocked == true) {
+                                         alarmBlocked = false;
+                                         sigemptyset(&nsig);
+                                         sigaddset(&nsig, SIGALRM);
+                                         sigprocmask(SIG_UNBLOCK, &nsig, 0);
+                                         }
+                                       */
+
+                                       /* I might be dying */
+                                       if ((CONTEXT(lastThread).flags & THREAD_FLAGS_KILLED)
+                                               != 0)
+                                       {
+                                               CONTEXT(lastThread).flags &= ~THREAD_FLAGS_KILLED;
+                                               exceptionptr = native_new_and_init(class_java_lang_ThreadDeath);
+                                       }
+                               }
+                               /* Now we kill the schedule and turn ints
+                                  back on */
+                               needReschedule = false;
+                               return;
+                       }
+               }
+               /* Nothing to run - wait for external event */
+               DBG( fprintf(stderr, "nothing more to do\n"); );
+               checkEvents(true);
+    }
+}
+
+#endif
diff --git a/threads/thread.h b/threads/thread.h
new file mode 100644 (file)
index 0000000..1f72d9e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * thread.h
+ * Thread support.
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#ifndef __thread_h
+#define __thread_h
+
+#ifdef USE_THREADS
+
+#include "../global.h"
+
+#define MAXTHREADS              256          /* schani */
+
+#define        THREADCLASS             "java/lang/Thread"
+#define        THREADGROUPCLASS        "java/lang/ThreadGroup"
+#define        THREADDEATHCLASS        "java/lang/ThreadDeath"
+
+#define        MIN_THREAD_PRIO         1
+#define        NORM_THREAD_PRIO        5
+#define        MAX_THREAD_PRIO         10
+
+#define        THREAD_SUSPENDED        0
+#define        THREAD_RUNNING          1
+#define        THREAD_DEAD             2
+#define        THREAD_KILL             3
+
+#define        THREAD_FLAGS_GENERAL            0
+#define        THREAD_FLAGS_NOSTACKALLOC       1
+#define THREAD_FLAGS_USER_SUSPEND       2  /* Flag explicit suspend() call */
+#define        THREAD_FLAGS_KILLED             4
+
+struct _thread;
+
+typedef struct _ctx
+{
+    bool               free;           /* schani */
+    u1                 status;
+    u1                 priority;
+    u1*                restorePoint;
+    u1*                stackMem;           /* includes guard page */
+    u1*                stackBase;
+    u1*                stackEnd;
+    u1*                usedStackTop;
+    s8                 time;
+    java_objectheader *exceptionptr;
+    struct _thread    *nextlive;
+    u1                 flags;
+} ctx;
+
+/*
+struct _stringClass;
+struct _object;
+*/
+
+/* This structure mirrors java.lang.ThreadGroup.h */
+
+typedef struct _threadGroup
+{
+    java_objectheader    header;
+    struct _threadGroup* parent;
+    java_objectheader*   name;
+    s4                   maxPrio;
+    s4                   destroyed;
+    s4                   daemon;
+    s4                   nthreads;
+    java_objectheader*   threads;
+    s4                   ngroups;
+    java_objectheader*   groups;
+} threadGroup;
+
+/* This structure mirrors java.lang.Thread.h */
+typedef struct _thread
+{
+    java_objectheader        header;
+    java_objectheader*       name;
+    s4                       priority;
+    struct _thread*          next;
+    s8                       PrivateInfo;
+    struct java_lang_Object* eetop;           /* ??? */
+    s4                       single_step;
+    s4                       daemon;
+    s4                       stillborn;
+    java_objectheader*       target;
+    s4                       interruptRequested;
+    threadGroup*             group;
+} thread;
+
+void initThreads(u1 *stackbottom);
+void startThread(thread*);
+void resumeThread(thread*);
+void iresumeThread(thread*);
+void suspendThread(thread*);
+void suspendOnQThread(thread*, thread**);
+void yieldThread(void);
+void killThread(thread*);
+void setPriorityThread(thread*, int);
+
+void sleepThread(s8);
+bool aliveThread(thread*);
+long framesThread(thread*);
+
+void reschedule(void);
+
+void checkEvents(bool block);
+
+extern int blockInts;
+extern bool needReschedule;
+extern thread *currentThread;
+extern ctx contexts[];
+extern int threadStackSize;
+
+extern thread *liveThreads;
+
+extern thread *threadQhead[MAX_THREAD_PRIO + 1];
+
+#define CONTEXT(_t)                                                     \
+        (contexts[(_t)->PrivateInfo - 1])
+
+#if 1
+#define        intsDisable()   blockInts++
+#define        intsRestore()   if (blockInts == 1 && needReschedule) {         \
+                           reschedule();                               \
+                       }                                               \
+                       blockInts--
+#else
+#define        intsDisable()   do { blockInts++; fprintf(stderr, "++: %d (%s:%d)\n", blockInts, __FILE__, __LINE__); } while (0)
+#define        intsRestore()   do { \
+                            if (blockInts == 1 && needReschedule) {    \
+                               reschedule();                           \
+                           }                                           \
+                           blockInts--;                                \
+                            fprintf(stderr, "--: %d (%s:%d)\n", blockInts, __FILE__, __LINE__);     \
+                        } while (0)
+#endif
+
+#else
+
+#define intsDisable()
+#define intsRestore()
+
+#endif
+
+#endif
diff --git a/threads/threadio.c b/threads/threadio.c
new file mode 100644 (file)
index 0000000..e538b40
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * threadCalls.c
+ * Support for threaded ops which may block (read, write, connect, etc.).
+ *
+ * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
+ */
+
+#define        DBG(s)                    
+
+#include "sysdep/defines.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "thread.h"
+
+/*
+ * We only need this stuff is we are using the internal thread system.
+ */
+#if defined(USE_INTERNAL_THREADS)
+
+#define        TH_READ         0
+#define        TH_WRITE        1
+#define        TH_ACCEPT       TH_READ
+#define        TH_CONNECT      TH_WRITE
+
+static int maxFd;
+static fd_set readsPending;
+static fd_set writesPending;
+static thread* readQ[FD_SETSIZE];
+static thread* writeQ[FD_SETSIZE];
+static struct timeval tm = { 0, 0 };
+
+void blockOnFile(int, int);
+void waitOnEvents(void);
+
+extern thread* currentThread;
+
+/* These are undefined because we do not yet support async I/O */
+#undef F_SETOWN
+#undef FIOSETOWN
+#undef O_ASYNC
+#undef FIOASYNC
+
+/*
+ * Create a threaded file descriptor.
+ */
+int
+threadedFileDescriptor(int fd)
+{
+#if !defined(BLOCKING_CALLS)
+    int r;
+    int on = 1;
+    int pid;
+
+    /* Make non-blocking */
+#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
+    r = fcntl(fd, F_GETFL, 0);
+    r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
+#elif defined(HAVE_IOCTL) && defined(FIONBIO)
+    r = ioctl(fd, FIONBIO, &on);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+
+    /* Allow socket to signal this process when new data is available */
+    pid = getpid();
+#if defined(HAVE_FCNTL) && defined(F_SETOWN)
+    r = fcntl(fd, F_SETOWN, pid);
+#elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
+    r = ioctl(fd, FIOSETOWN, &pid);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+
+#if defined(HAVE_FCNTL) && defined(O_ASYNC)
+    r = fcntl(fd, F_GETFL, 0);
+    r = fcntl(fd, F_SETFL, r|O_ASYNC);
+#elif defined(HAVE_IOCTL) && defined(FIOASYNC)
+    r = ioctl(fd, FIOASYNC, &on);
+#else
+    r = 0;
+#endif
+    if (r < 0)
+    {
+       return (r);
+    }
+#endif
+    return (fd);
+}
+
+/*
+ * Threaded create socket.
+ */
+int
+threadedSocket(int af, int type, int proto)
+{
+    int fd;
+    int r;
+    int on = 1;
+    int pid;
+
+    fd = socket(af, type, proto);
+    return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded file open.
+ */
+int
+threadedOpen(char* path, int flags, int mode)
+{
+    int fd;
+    int r;
+    int on = 1;
+    int pid;
+
+    fd = open(path, flags, mode);
+    return (threadedFileDescriptor(fd));
+}
+
+/*
+ * Threaded socket connect.
+ */
+int
+threadedConnect(int fd, struct sockaddr* addr, int len)
+{
+    int r;
+
+    r = connect(fd, addr, len);
+#if !defined(BLOCKING_CALLS)
+    if ((r < 0)
+       && (errno == EINPROGRESS || errno == EALREADY
+           || errno == EWOULDBLOCK)) {
+       blockOnFile(fd, TH_CONNECT);
+       r = 0; /* Assume it's okay when we get released */
+    }
+#endif
+
+    return (r);
+}
+
+/*
+ * Threaded socket accept.
+ */
+int
+threadedAccept(int fd, struct sockaddr* addr, int* len)
+{
+    int r;
+    int on = 1;
+
+    for (;;)
+    {
+#if defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_ACCEPT);
+#endif
+       r = accept(fd, addr, len);
+       if (r >= 0
+           || !(errno == EINPROGRESS || errno == EALREADY
+                || errno == EWOULDBLOCK))
+       {
+           break;
+       }
+#if !defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_ACCEPT);
+#endif
+    }
+    return (threadedFileDescriptor(r));
+}
+
+/*
+ * Read but only if we can.
+ */
+int
+threadedRead(int fd, char* buf, int len)
+{
+    int r;
+
+    DBG(   printf("threadedRead\n");          )
+
+#if defined(BLOCKING_CALLS)
+    blockOnFile(fd, TH_READ);
+#endif
+    for (;;)
+    {
+       r = read(fd, buf, len);
+       if (r < 0
+           && (errno == EAGAIN || errno == EWOULDBLOCK
+               || errno == EINTR))
+       {
+           blockOnFile(fd, TH_READ);
+           continue;
+       }
+       return (r);
+    }
+}
+
+/*
+ * Write but only if we can.
+ */
+int
+threadedWrite(int fd, char* buf, int len)
+{
+    int r;
+    char* ptr;
+
+    ptr = buf;
+    r = 1;
+
+    DBG(    printf("threadedWrite %dbytes\n",len);      )
+
+    while (len > 0 && r > 0)
+    {
+#if defined(BLOCKING_CALLS)
+       blockOnFile(fd, TH_WRITE);
+#endif
+       r = write(fd, ptr, len);
+       if (r < 0
+           && (errno == EAGAIN || errno == EWOULDBLOCK
+               || errno == EINTR))
+       {
+#if !defined(BLOCKING_CALLS)
+           blockOnFile(fd, TH_WRITE);
+#endif
+           r = 1;
+       }
+       else
+       {
+           ptr += r;
+           len -= r;
+       }
+    }
+    return (ptr - buf);
+}
+
+/*
+ * An attempt to access a file would block, so suspend the thread until
+ * it will happen.
+ */
+void
+blockOnFile(int fd, int op)
+{
+DBG(   printf("blockOnFile()\n");                                      )
+
+    intsDisable();
+
+    if (fd > maxFd)
+    {
+       maxFd = fd;
+    }
+    if (op == TH_READ)
+    {
+       FD_SET(fd, &readsPending);
+       suspendOnQThread(currentThread, &readQ[fd]);
+       FD_CLR(fd, &readsPending);
+    }
+    else
+    {
+       FD_SET(fd, &writesPending);
+       suspendOnQThread(currentThread, &writeQ[fd]);
+       FD_CLR(fd, &writesPending);
+    }
+
+    intsRestore();
+}
+
+/*
+ * Check if some file descriptor or other event to become ready.
+ * Block if required (but make sure we can still take timer interrupts).
+ */
+void
+checkEvents(bool block)
+{
+    int r;
+    fd_set rd;
+    fd_set wr;
+    thread* tid;
+    thread* ntid;
+    int i;
+    int b;
+
+DBG(   printf("checkEvents block:%d\n", block);                        )
+
+#if defined(FD_COPY)
+    FD_COPY(&readsPending, &rd);
+    FD_COPY(&writesPending, &wr);
+#else
+    memcpy(&rd, &readsPending, sizeof(rd));
+    memcpy(&wr, &writesPending, sizeof(wr));
+#endif
+
+    /* 
+     * If select() is called with indefinite wait, we have to make sure
+     * we can get interrupted by timer events. 
+     */
+    if (block == true)
+    {
+       b = blockInts;
+       blockInts = 0;
+       r = select(maxFd+1, &rd, &wr, 0, 0);
+       blockInts = b;
+    }
+    else
+    {
+       r = select(maxFd+1, &rd, &wr, 0, &tm);
+    }
+
+    /* We must be holding off interrupts before we start playing with
+     * the read and write queues.  This should be already done but a
+     * quick check never hurt anyone.
+     */
+    assert(blockInts > 0);
+
+DBG(   printf("Select returns %d\n", r);                               )
+
+    for (i = 0; r > 0 && i <= maxFd; i++)
+    {
+       if (readQ[i] != 0 && FD_ISSET(i, &rd))
+       {
+           for (tid = readQ[i]; tid != 0; tid = ntid)
+           {
+               ntid = tid->next;
+               iresumeThread(tid);
+           }
+           readQ[i] = 0;
+           r--;
+       }
+       if (writeQ[i] != 0 && FD_ISSET(i, &wr))
+       {
+           for (tid = writeQ[i]; tid != 0; tid = ntid)
+           {
+               ntid = tid->next;
+               iresumeThread(tid);
+           }
+           writeQ[i] = 0;
+           r--;
+       }
+    }
+}
+#endif
diff --git a/threads/threadio.h b/threads/threadio.h
new file mode 100644 (file)
index 0000000..1e9d5c2
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- c -*- */
+
+#ifndef __threadio_h_
+#define __threadio_h_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "../global.h"
+
+#ifdef USE_THREADS
+int threadedFileDescriptor(int fd);
+int threadedSocket(int af, int type, int proto);
+int threadedOpen(char* path, int flags, int mode);
+int threadedConnect(int fd, struct sockaddr* addr, int len);
+int threadedAccept(int fd, struct sockaddr* addr, int* len);
+int threadedRead(int fd, char* buf, int len);
+int threadedWrite(int fd, char* buf, int len);
+#else
+#define threadedFileDescriptor(fd)
+#define threadedRead(fd,buf,len)          read(fd,buf,len)
+#define threadedWrite(fd,buf,len)         write(fd,buf,len)
+#endif
+
+
+#endif
diff --git a/toolbox/Makefile b/toolbox/Makefile
new file mode 100755 (executable)
index 0000000..191d8a2
--- /dev/null
@@ -0,0 +1,28 @@
+################################################################################
+#                 Makefile for the program independent toolbox                 #
+################################################################################
+#
+# Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+#
+# See the file COPYRIGHT for information on usage and disclaimer of warranties
+#
+# Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+#
+# Last Change: 1997/10/30
+#
+################################################################################
+
+OBJECTS = memory.o loging.o chain.o tree.o list.o
+
+toolbox.a: $(OBJECTS) Makefile
+       rm -f toolbox.a
+       ar qcs toolbox.a $(OBJECTS)
+       
+memory.o: memory.c memory.h loging.h
+loging.o: loging.c loging.h
+chain.o: chain.c chain.h memory.h
+tree.o: tree.c tree.h memory.h
+list.o: list.c list.h
+
+clean: 
+       rm -f *.o *.a
diff --git a/toolbox/chain.c b/toolbox/chain.c
new file mode 100644 (file)
index 0000000..7e50617
--- /dev/null
@@ -0,0 +1,243 @@
+/************************* toolbox/chain.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see chain.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "chain.h"
+
+
+
+chain *chain_new ()
+{
+       chain *c;
+       
+       c = NEW (chain);
+       c -> usedump = 0;
+       c -> first = NULL;
+       c -> last = NULL;
+       c -> active = NULL;
+
+       return c;
+}
+
+chain *chain_dnew ()
+{
+       chain *c;
+       
+       c = DNEW (chain);
+       c -> usedump = 1;
+       c -> first = NULL;
+       c -> last = NULL;
+       c -> active = NULL;
+
+       return c;
+}
+
+
+void chain_free (chain *c)
+{
+       chainlink *l;
+
+       assert (! c->usedump);
+
+       l = c->first;
+       while (l) {
+               chainlink *nextl = l->next;
+               
+               FREE (l, chainlink);
+               l = nextl;      
+               }
+       
+       FREE (c, chain);
+}
+
+
+void chain_addafter(chain *c, void *element)
+{
+       chainlink *active,*newlink;
+
+    active = c->active;
+
+       if (c -> usedump) newlink = DNEW (chainlink);
+       else              newlink = NEW (chainlink);
+
+       newlink -> element = element;
+       
+       if (active) {
+               newlink -> next = active -> next;
+               newlink -> prev = active;
+               
+               active -> next = newlink;
+               if (newlink -> next) newlink -> next -> prev = newlink;
+                               else c -> last = newlink;
+               }
+       else {  
+               newlink -> next = NULL;
+               newlink -> prev = NULL;
+
+               c -> active = newlink;  
+               c -> first = newlink;
+               c -> last = newlink;
+               }
+}
+
+
+void chain_addbefore(chain *c, void *element)
+{
+       chainlink *active,*newlink;
+
+    active = c->active;
+
+       if (c -> usedump) newlink = DNEW (chainlink);
+       else              newlink = NEW (chainlink);
+       
+       newlink -> element = element;
+       
+       if (active) {
+               newlink -> next = active;
+               newlink -> prev = active -> prev;
+               
+               active -> prev = newlink;
+               if (newlink -> prev) newlink -> prev -> next = newlink;
+               else                 c -> first = newlink;
+               }
+       else {  
+               newlink -> next = NULL;
+               newlink -> prev = NULL;
+
+               c -> active = newlink;  
+               c -> first = newlink;
+               c -> last = newlink;
+               }
+}
+
+void chain_addlast (chain *c, void *e)
+{
+       chain_last (c);
+       chain_addafter (c, e);
+}
+
+void chain_addfirst (chain *c, void *e)
+{
+       chain_first (c);
+       chain_addbefore (c, e);
+}
+
+
+void chain_remove (chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       assert (active);
+
+       if (active -> next) {
+               active -> next -> prev = active -> prev;
+               }
+       else {
+               c -> last = active -> prev;
+               }
+       
+       if (active -> prev) {
+               active -> prev -> next = active -> next;
+               }
+       else {
+               c -> first = active -> next;
+               }
+
+
+       if (active->prev) 
+               c -> active = active->prev;
+       else
+               c -> active = active->next;
+
+       if (! c -> usedump) FREE (active, chainlink);
+}
+
+
+void *chain_remove_go_prev (chain *c)
+{
+       chain_remove (c);
+       return chain_this (c);
+}
+
+
+
+void chain_removespecific(chain *c, void *e)
+{
+       void *ce;
+       
+       ce = chain_first (c);
+       while (ce) {
+               if (e == ce) { chain_remove (c); return; }
+        ce = chain_next (c);           
+               }
+               
+}
+
+void *chain_next(chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       if (!active) return NULL;
+       
+       if (active -> next) {
+               c -> active = active -> next;
+               return c -> active -> element;
+               }
+               
+       return NULL;
+}
+
+void *chain_prev(chain *c)
+{
+       chainlink *active;
+       
+       active = c -> active;
+       if (!active) return NULL;
+       
+       if (active -> prev) {
+               c -> active = active -> prev;
+               return c -> active -> element;
+               }
+
+       return NULL;
+}
+
+
+void *chain_this(chain *c)
+{
+       if (c -> active) return c -> active -> element;
+       return NULL;
+}
+
+
+void *chain_first(chain *c)
+{
+       c -> active = c -> first;
+       if (c -> active) return c -> active -> element;
+       return NULL;
+}
+
+void *chain_last(chain *c)
+{
+       c -> active = c -> last;
+       if (c -> active) return c -> active -> element;;
+       return NULL;
+}
+
diff --git a/toolbox/chain.h b/toolbox/chain.h
new file mode 100644 (file)
index 0000000..e065c07
--- /dev/null
@@ -0,0 +1,92 @@
+/************************* toolbox/chain.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       dient zur Verwaltung doppelt verketteter Listen mit externer Verkettung
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct chainlink {          /* Struktur f"ur ein Listenelement */
+       struct chainlink *next,*prev;
+       void *element;
+       } chainlink;
+
+typedef struct chain {             /* Struktur f"ur eine Liste */
+       int  usedump;   
+
+       chainlink *first,*last;
+       chainlink *active;
+       } chain;
+
+
+chain *chain_new ();
+chain *chain_dnew ();
+void chain_free(chain *c);
+
+void chain_addafter(chain *c, void *element);
+void chain_addbefore(chain *c, void *element);
+void chain_addlast (chain *c, void *element);
+void chain_addfirst (chain *c, void *element);
+
+void chain_remove(chain *c);
+void *chain_remove_go_prev(chain *c);
+void chain_removespecific(chain *c, void *element);
+
+void *chain_next(chain *c);
+void *chain_prev(chain *c);
+void *chain_this(chain *c);
+
+void *chain_first(chain *c);
+void *chain_last(chain *c);
+
+
+/*
+--------------------------- Schnittstellenbeschreibung ------------------------
+
+Bei Verwendung dieser Funktionen f"ur die Listenverwaltung mu"s, im
+Gegenstatz zum Modul 'list', keine zus"atzliche Vorbereitung in den 
+Element-Strukturen gemacht werden.
+
+Diese Funktionen sind daher auch ein wenig langsamer und brauchen 
+mehr Speicher.
+
+Eine neue Liste wird mit 
+                 chain_new
+       oder  chain_dnew 
+angelegt. Der Unterschied ist, da"s bei der zweiten Variante alle
+zus"atzlichen Datenstrukturen am DUMP-Speicher angelegt werden (was
+schneller geht, und ein explizites Freigeben am Ende der Verarbeitung
+unn"otig macht). Dabei mu"s man aber achtgeben, da"s man nicht 
+versehentlich Teile dieser Strukturen durch ein verfr"uhtes 'dump_release'
+freigibt.
+
+Eine nicht mehr verwendete Liste kann mit
+               chain_free
+freigegeben werden (nur verwenden, wenn mit 'chain_new' angefordert)
+
+
+Das Eintragen neuer Elemente geht sehr einfach mit:
+       chain_addafter, chain_addlast, chain_addbefore, chain_addfirst          
+       
+Durchsuchen der Liste mit:
+       chain_first, chain_last, chain_prev, chain_next, chain_this
+       
+L"oschen von Elementen aus der Liste:
+       chain_remove, chain_remove_go_prev, chain_removespecific
+       
+       
+ACHTUNG: In den zu verkettenden Elementen gibt es ja (wie oben gesagt) keine
+       Referenzen auf die Liste oder irgendwelche Listenknoten, deshalb k"onnen
+       die Elemente nicht als Ortsangabe innerhalb der Liste fungieren.
+       Es gibt vielmehr ein Art 'Cursor', der ein Element als das gerade
+       aktuelle festh"alt, und alle Ein-/und Ausf"ugeoperationen geschehen
+       relativ zu diesem Cursor.
+
+*/
+
diff --git a/toolbox/list.c b/toolbox/list.c
new file mode 100644 (file)
index 0000000..6183684
--- /dev/null
@@ -0,0 +1,107 @@
+/************************** toolbox/list.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see chain.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "list.h"
+
+
+void list_init (list *l, int nodeoffset)
+{
+       l->first = NULL;
+       l->last = NULL;
+       l->nodeoffset = nodeoffset;
+}
+
+void list_addlast (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+       if (l->last) {
+               n->prev = l->last;
+               n->next = NULL;
+               l->last->next = n;
+               l->last = n;
+               }
+       else {
+               n->prev = NULL;
+               n->next = NULL;
+               l->last = n;
+               l->first = n;
+               }
+}
+
+void list_addfirst (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+
+       if (l->first) {
+               n->prev = NULL;
+               n->next = l->first;
+               l->first->prev = n;
+               l->first = n;
+               }
+       else {
+               n->prev = NULL;
+               n->next = NULL;
+               l->last = n;
+               l->first = n;
+               }
+}
+
+
+void list_remove (list *l, void *element)
+{
+       listnode *n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       
+       if (n->next) n->next->prev = n->prev;
+               else l->last = n->prev;
+       if (n->prev) n->prev->next = n->next;
+               else l->first = n->next;
+}
+
+void *list_first (list *l)
+{
+       if (!l->first) return NULL;
+       return ((char*) l->first) - l->nodeoffset;
+}
+
+
+void *list_last (list *l)
+{
+       if (!l->last) return NULL;
+       return ((char*) l->last) - l->nodeoffset;
+}
+
+
+void *list_next (list *l, void *element)
+{
+       listnode *n;
+       n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       if (!n->next) return NULL;
+       return ((char*) n->next) - l->nodeoffset;
+}
+
+       
+void *list_prev (list *l, void *element)
+{
+       listnode *n;
+       n = (listnode*) ( ((char*) element) + l->nodeoffset );
+       if (!n->prev) return NULL;
+       return ((char*) n->prev) - l->nodeoffset;
+}
+
diff --git a/toolbox/list.h b/toolbox/list.h
new file mode 100644 (file)
index 0000000..22f7ec0
--- /dev/null
@@ -0,0 +1,97 @@
+/************************** toolbox/list.h *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Verwaltung von doppelt verketteten Listen. 
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef struct listnode {           /* Struktur f"ur ein Listenelement */
+       struct listnode *next,*prev;
+       } listnode;
+
+typedef struct list {               /* Struktur f"ur den Listenkopf */
+       listnode *first,*last;
+       int nodeoffset;
+       } list;
+
+
+void list_init (list *l, int nodeoffset);
+
+void list_addlast (list *l, void *element);
+void list_addfirst (list *l, void *element);
+
+void list_remove (list *l, void *element);
+void *list_first (list *l);
+void *list_last (list *l);
+
+void *list_next (list *l, void *element);
+void *list_prev (list *l, void *element);
+
+
+/*
+---------------------- Schnittstellenbeschreibung -----------------------------
+
+Die Listenverwaltung mit diesem Modul geht so vor sich:
+       
+       - jede Struktur, die in die Liste eingeh"angt werden soll, mu"s 
+         eine Komponente vom Typ 'listnode' haben.
+         
+       - es mu"s ein Struktur vom Typ 'list' bereitgestellt werden.
+       
+       - die Funktion list_init (l, nodeoffset) initialisiert diese Struktur,
+         dabei gibt der nodeoffset den Offset der 'listnode'-Komponente in
+         den Knotenstrukturen an.
+         
+       - Einf"ugen, Aush"angen und Suchen von Elementen der Liste geht mit
+         den "ubrigen Funktionen.
+         
+Zum besseren Verst"andnis ein kleines Beispiel:
+
+
+       void bsp() {
+               struct node {
+                       listnode linkage;
+                       int value;
+                       } a,b,c, *el;
+                       
+               list l;
+               
+               a.value = 7;
+               b.value = 9;
+               c.value = 11;
+               
+               list_init (&l, OFFSET(struct node,linkage) );
+               list_addlast (&l, a);
+               list_addlast (&l, b);
+               list_addlast (&l, c);
+               
+               e = list_first (&l);
+               while (e) {
+                       printf ("Element: %d\n", e->value);
+                       e = list_next (&l,e);
+                       }
+       }
+       
+       
+       Dieses Programm w"urde also folgendes ausgeben:
+               7
+               9
+               11
+
+
+
+Der Grund, warum beim Initialisieren der Liste der Offset mitangegeben
+werden mu"s, ist der da"s ein und das selbe Datenelement gleichzeitig
+in verschiedenen Listen eingeh"angt werden kann (f"ur jede Liste mu"s
+also eine Komponente vom Typ 'listnode' im Element enthalten sein).
+
+*/
+
diff --git a/toolbox/loging.c b/toolbox/loging.c
new file mode 100644 (file)
index 0000000..e4b9f23
--- /dev/null
@@ -0,0 +1,136 @@
+/************************* toolbox/loging.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see loging.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "loging.h"
+
+/***************************************************************************
+                        LOGFILE - BEHANDLUNG 
+***************************************************************************/
+
+char logtext[MAXLOGTEXT];   /* Musz mit dem gewuenschten Text vor */
+                            /* Aufruf von dolog() beschrieben werden */
+
+
+FILE *logfile = NULL;
+
+
+
+
+void log_init(char *fname)
+{
+       if (fname) {
+               if (fname[0]) {
+                       logfile = fopen(fname, "w");
+                       }
+               }
+}
+
+
+
+/*********************** Funktion: dolog ************************************
+
+Gibt den in logtext stehenden Text auf die Protokollierungsdatei
+aus (wenn sie offen ist) und auszerdem auf stdout. 
+
+**************************************************************************/
+
+void dolog()
+{
+       if (logfile) {
+               fprintf (logfile, "%s\n",logtext);
+               fflush (logfile);
+               }
+       else {
+               printf ("LOG: %s\n",logtext);
+               fflush (stdout);
+               }
+}
+
+/********************* Funktion: log_text ********************************/
+
+void log_text (char *text)
+{
+       sprintf (logtext, "%s",text);
+       dolog();
+}
+
+
+/********************* Funktion: log_cputime ****************************/
+
+void log_cputime ()
+{
+   long int t;
+   int sec,usec;
+
+   t = getcputime();
+   sec = t/1000000;
+   usec = t%1000000;
+
+   sprintf (logtext, "Total CPU usage: %d seconds and %d milliseconds",
+            sec,usec/1000);
+   dolog();
+}
+
+
+
+/************************** Funktion: error *******************************
+
+Wie dolog(), aber das Programm wird auszerdem sofort terminiert.
+
+**************************************************************************/
+
+void error()
+{
+       if (logfile) {
+               fprintf (logfile, "ERROR: %s\n", logtext);
+               }   
+       printf ("ERROR: %s\n",logtext);
+       exit(10);
+}
+
+
+/************************ Funktion: panic (txt) ****************************
+
+  Wie error(), jedoch wird der auszugebende Text als Argument uebergeben
+
+***************************************************************************/
+
+void panic(char *txt)
+{
+       sprintf (logtext, "%s", txt);
+       error();
+}
+
+
+/********************** Funktion: getcputime ********************************
+
+       liefert die verbrauchte CPU-Zeit im Mikrosekunden
+       
+****************************************************************************/
+
+long int getcputime()
+{
+   struct rusage ru;
+   int sec,usec;
+
+   getrusage (RUSAGE_SELF, &ru);
+   sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+   usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+   return sec*1000000 + usec;
+}
+
diff --git a/toolbox/loging.h b/toolbox/loging.h
new file mode 100644 (file)
index 0000000..d28472b
--- /dev/null
@@ -0,0 +1,53 @@
+/************************* toolbox/loging.h ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Stellt Funktionen f"urs Logging zur Verf"ugung
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define PANICIF(when,txt)  if(when)panic(txt)
+
+#define MAXLOGTEXT 500
+extern char logtext[MAXLOGTEXT];
+
+void log_init(char *fname);
+void log_text(char *txt);
+
+void log_cputime();
+
+void dolog();
+void error();
+void panic(char *txt);
+
+long int getcputime();
+
+
+/*
+
+-------------------------- Schnittstellenbeschreibung -------------------------
+
+log_init .... Initialisiert das Logfile-System 
+               fname ....... Dateiname f"ur die Protokollierungsdatei
+               keepfile .... 1, wenn die alte Datei nicht gel"oscht werden soll
+               echostdout .. 1, wenn auch auf stdout ausgegeben werden soll
+               
+log_text .... Gibt einen Text auf das Logfile aus
+log_cputime . Gibt eine Information "uber die verbrauchte CPU-Zeit aus
+dolog ....... Gibt den Inhalt von logtext aus
+error ....... Gibt den Inhalt von logtext aus, und stoppt das System
+panic ....... Gibt eine Text auf das Logfile aus
+
+logtext ..... dieses globale Array mu"s vor Benutzung der Funktionen 'log' 
+              oder 'error' mit dem auszugebenen Text bef"ullt werden.
+
+getcputimew . gibt die vom Programm verbrauchte CPU-Zeit in
+              Mikrosekunden zur"uck
+
+*/
diff --git a/toolbox/memory.c b/toolbox/memory.c
new file mode 100644 (file)
index 0000000..2cc8e94
--- /dev/null
@@ -0,0 +1,458 @@
+/************************* toolbox/memory.c ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see memory.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "../callargs.h"
+#include "loging.h"
+#include "memory.h"
+
+
+       /********* allgemeine Typen, Variablen und Hilfsfunktionen *********/
+
+#define DUMPBLOCKSIZE  (2<<18)
+#define ALIGNSIZE           8
+
+typedef struct dumplist {
+       struct dumplist *prev;
+       char *dumpmem;
+} dumplist;
+
+
+
+long int memoryusage = 0;
+
+long int dumpsize = 0;
+long int dumpspace = 0;
+dumplist *topdumpblock = NULL;
+
+long int maxmemusage = 0;
+long int maxdumpsize = 0;
+
+/* #define TRACECALLARGS */
+
+#ifdef TRACECALLARGS
+static char  nomallocmem[16777216];
+static char *nomalloctop = nomallocmem + 16777216;
+static char *nomallocptr = nomallocmem;
+
+static void *lit_checked_alloc (int length)
+{
+       void *m;
+
+       nomallocptr = (void*) ALIGN ((long) nomallocptr, ALIGNSIZE);
+       
+       m = nomallocptr;
+       nomallocptr += length;
+       if (nomallocptr > nomalloctop) panic ("Out of memory");
+       return m;
+}
+
+#else
+
+static void *lit_checked_alloc (int length)
+{
+       void *m = malloc(length);
+       if (!m) panic ("Out of memory");
+       return m;
+}
+
+#endif
+
+
+static void *checked_alloc (int length)
+{
+       void *m = malloc(length);
+       if (!m) panic ("Out of memory");
+       return m;
+}
+
+static int mmapcodesize = 0;
+static void *mmapcodeptr = NULL;
+
+void *mem_mmap(int length)
+{
+       void *retptr;
+
+       length = (ALIGN(length,ALIGNSIZE));
+       if (length > mmapcodesize) {
+               mmapcodesize = 0x10000;
+               if (length > mmapcodesize)
+                       mmapcodesize = length;
+               mmapcodesize = (ALIGN(mmapcodesize, getpagesize()));
+               mmapcodeptr = mmap (NULL, (size_t) mmapcodesize,
+                             PROT_READ | PROT_WRITE | PROT_EXEC,
+                             MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t) 0);
+               if (mmapcodeptr == (void*) -1)
+                       panic ("Out of memory");
+               }
+       retptr = mmapcodeptr;
+       mmapcodeptr = (void*) ((char*) mmapcodeptr + length);
+       mmapcodesize -= length;
+       return retptr;
+}
+
+
+#ifdef DEBUG
+
+       /************ Sichere Version des Speichermanages **************/
+
+
+typedef struct memblock {
+       struct memblock *prev,*next;
+       int length;
+} memblock;
+
+#define BLOCKOFFSET    (ALIGN(sizeof(memblock),ALIGNSIZE))
+
+struct memblock *firstmemblock;
+
+
+
+void *mem_alloc(int length)
+{
+       memblock *mb;
+
+       if (length==0) return NULL;
+       mb = checked_alloc (length + BLOCKOFFSET);
+
+       mb -> prev = NULL;
+       mb -> next = firstmemblock;     
+       mb -> length = length;
+
+       if (firstmemblock) firstmemblock -> prev = mb;
+       firstmemblock = mb;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+       return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void *lit_mem_alloc(int length)
+{
+       memblock *mb;
+
+       if (length==0) return NULL;
+       mb = lit_checked_alloc (length + BLOCKOFFSET);
+
+       mb -> prev = NULL;
+       mb -> next = firstmemblock;     
+       mb -> length = length;
+
+       if (firstmemblock) firstmemblock -> prev = mb;
+       firstmemblock = mb;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+
+       return ((char*) mb) + BLOCKOFFSET;
+}
+
+
+void mem_free(void *m, int length)
+{
+       memblock *mb;
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+       
+       if (mb->length != length) {
+               sprintf (logtext, 
+                        "Memory block of size %d has been return as size %d",
+                        mb->length, length);
+               error();
+               }
+               
+       if (mb->prev) mb->prev->next = mb->next;
+                else firstmemblock = mb->next;
+       if (mb->next) mb->next->prev = mb->prev;
+
+       free (mb);
+
+       memoryusage -= length;
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+       memblock *mb;
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       mb = (memblock*) (((char*) m) - BLOCKOFFSET);
+       
+       if (mb->length != length) {
+               sprintf (logtext, 
+                        "Memory block of size %d has been return as size %d",
+                        mb->length, length);
+               error();
+               }
+               
+       if (mb->prev) mb->prev->next = mb->next;
+                else firstmemblock = mb->next;
+       if (mb->next) mb->next->prev = mb->prev;
+
+#ifdef TRACECALLARGS
+#else
+       free (mb);
+#endif
+
+       memoryusage -= length;
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+       void *m2;
+       
+       m2 = mem_alloc (len2);
+       memcpy (m2, m1, len1);
+       mem_free (m1, len1);
+
+       return m2;
+}
+
+
+
+
+static void mem_characterlog (unsigned char *m, int len)
+{
+#      define LINESIZE 16
+       int z,i;
+       
+       for (z=0; z<len; z+=LINESIZE) {
+               sprintf (logtext, "   ");
+                       
+               for (i=z; i<(z+LINESIZE) && i<len; i++) {
+                       sprintf (logtext+strlen(logtext), "%2x ", m[i]);
+                       }
+               for (; i<(z+LINESIZE); i++) {
+                       sprintf (logtext+strlen(logtext), "   ");
+                       }
+                                       
+               sprintf (logtext+strlen(logtext),"   ");
+               for (i=z; i<(z+LINESIZE) && i<len; i++) {
+                       sprintf (logtext+strlen(logtext),
+                            "%c", (m[i]>=' ' && m[i]<=127) ? m[i] : '.');
+                       }
+                       
+               dolog();
+               }
+}
+
+#else
+               /******* Schnelle Version des Speichermanagers ******/
+
+
+void *mem_alloc(int length)
+{
+       if (length==0) return NULL;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+       
+       return checked_alloc (length);
+}
+
+
+void *lit_mem_alloc(int length)
+{
+       if (length==0) return NULL;
+
+       memoryusage += length;
+       if (memoryusage > maxmemusage) maxmemusage = memoryusage;
+       
+       return lit_checked_alloc (length);
+}
+
+
+void mem_free(void *m, int length)
+{
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       memoryusage -= length;
+
+       free (m);
+}
+
+
+void lit_mem_free(void *m, int length)
+{
+       if (!m) {
+               if (length==0) return;
+               panic ("returned memoryblock with address NULL, length != 0");
+               }
+
+       memoryusage -= length;
+
+#ifdef TRACECALLARGS
+#else
+       free (m);
+#endif
+}
+
+
+void *mem_realloc (void *m1, int len1, int len2)
+{
+       void *m2;
+
+       if (!m1) {
+               if (len1!=0) 
+                 panic ("reallocating memoryblock with address NULL, length != 0");
+               }
+               
+       memoryusage = (memoryusage - len1) + len2;
+
+       m2 = realloc (m1, len2);
+       if (!m2) panic ("Out of memory");
+       return m2;
+}
+
+
+#endif
+
+               /******* allgemeine Teile des Speichermanagers ******/
+
+
+
+long int mem_usage()
+{
+       return memoryusage;
+}
+
+
+
+
+
+void *dump_alloc(int length)
+{
+       void *m;
+
+        if (length==0) return NULL;
+       
+       length = ALIGN (length, ALIGNSIZE);
+
+       assert (length <= DUMPBLOCKSIZE);
+       assert (length > 0);
+
+       if (dumpsize + length > dumpspace) {
+               dumplist *newdumpblock = checked_alloc (sizeof(dumplist));
+
+               newdumpblock -> prev = topdumpblock;
+               topdumpblock = newdumpblock;
+
+               newdumpblock -> dumpmem = checked_alloc (DUMPBLOCKSIZE);
+
+               dumpsize = dumpspace;
+               dumpspace += DUMPBLOCKSIZE;             
+               }
+       
+       m = topdumpblock -> dumpmem + DUMPBLOCKSIZE - (dumpspace - dumpsize);
+       dumpsize += length;
+       
+       if (dumpsize > maxdumpsize) {
+               maxdumpsize = dumpsize;
+               }
+               
+       return m;
+}   
+
+
+void *dump_realloc(void *ptr, int len1, int len2)
+{
+       void *p2 = dump_alloc (len2);
+       memcpy (p2, ptr, len1); 
+       return p2;
+}
+
+
+long int dump_size()
+{
+       return dumpsize;
+}
+
+
+void dump_release(long int size)
+{
+       assert (size >= 0 && size <= dumpsize);
+
+       dumpsize = size;
+       
+       while (dumpspace  >  dumpsize + DUMPBLOCKSIZE) {
+               dumplist *oldtop = topdumpblock;
+               
+               topdumpblock = oldtop -> prev;
+               dumpspace -= DUMPBLOCKSIZE;
+               
+#ifdef TRACECALLARGS
+#else
+               free (oldtop -> dumpmem);
+               free (oldtop);
+#endif
+               }               
+}
+
+
+
+
+void mem_usagelog (int givewarnings)
+{
+       if ((memoryusage!=0) && givewarnings) {
+               sprintf (logtext, "Allocated memory not returned: %d",
+                     (int)memoryusage);
+               dolog();
+
+#ifdef DEBUG
+               { 
+               memblock *mb = firstmemblock;
+               while (mb) {
+                       sprintf (logtext, "   Memory block size: %d", 
+                         (int)(mb->length) );
+                       dolog();
+                       mem_characterlog ( ((unsigned char*)mb) + BLOCKOFFSET, mb->length);
+                       mb = mb->next;
+                       }
+               }
+#endif
+                       
+               }
+
+       if ((dumpsize!=0) && givewarnings) {
+               sprintf (logtext, "Dump memory not returned: %d",(int)dumpsize);
+               dolog();
+               }
+
+
+       sprintf (logtext, "Random/Dump - memory usage: %dK/%dK", 
+             (int)((maxmemusage+1023)/1024), 
+             (int)((maxdumpsize+1023)/1024) );
+       dolog();
+       
+}
+
diff --git a/toolbox/memory.h b/toolbox/memory.h
new file mode 100644 (file)
index 0000000..c4122f9
--- /dev/null
@@ -0,0 +1,121 @@
+/************************* toolbox/memory.h ************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Headerfiles und Makros f"ur die Speicherverwaltung.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#define CODEMMAP
+
+#define ALIGN(pos,size)       ( ( ((pos)+(size)-1) / (size))*(size) )
+#define PADDING(pos,size)     ( ALIGN((pos),(size)) - (pos) )
+#define OFFSET(s,el)          ( (int) &( ((s*)0) -> el ) )
+
+
+#define NEW(type)             ((type*) mem_alloc ( sizeof(type) ))
+#define FREE(ptr,type)        mem_free (ptr, sizeof(type) )
+
+#define LNEW(type)             ((type*) lit_mem_alloc ( sizeof(type) ))
+#define LFREE(ptr,type)        lit_mem_free (ptr, sizeof(type) )
+
+#define MNEW(type,num)        ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define MFREE(ptr,type,num)   mem_free (ptr, sizeof(type) * (num) )
+#define MREALLOC(ptr,type,num1,num2) mem_realloc (ptr, sizeof(type) * (num1), \
+                                                       sizeof(type) * (num2) )
+
+#define DNEW(type)            ((type*) dump_alloc ( sizeof(type) ))
+#define DMNEW(type,num)       ((type*) dump_alloc ( sizeof(type) * (num) ))
+#define DMREALLOC(ptr,type,num1,num2)  dump_realloc (ptr, sizeof(type)*(num1),\
+                                                       sizeof(type) * (num2) )
+
+#define MCOPY(dest,src,type,num)  memcpy (dest,src, sizeof(type)* (num) )
+
+#ifdef CODEMMAP
+#define CNEW(type,num)        ((type*) mem_mmap ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)
+#else
+#define CNEW(type,num)        ((type*) mem_alloc ( sizeof(type) * (num) ))
+#define CFREE(ptr,num)        mem_free (ptr, num)
+#endif
+
+void *mem_alloc(int length);
+void *mem_mmap(int length);
+void *lit_mem_alloc(int length);
+void mem_free(void *m, int length);
+void lit_mem_free(void *m, int length);
+void *mem_realloc(void *m, int len1, int len2);
+long int mem_usage();
+
+void *dump_alloc(int length);
+void *dump_realloc(void *m, int len1, int len2);
+long int dump_size();
+void dump_release(long int size);
+
+void mem_usagelog(int givewarnings);
+/* 
+---------------------------- Schnittstellenbeschreibung -----------------------
+
+Der Speicherverwalter hat zwei m"ogliche Arten Speicher zu reservieren
+und freizugeben:
+
+       1.   explizites Anfordern / Freigeben
+
+                       mem_alloc ..... Anfordern eines Speicherblocks 
+                       mem_free ...... Freigeben eines Speicherblocks
+                       mem_realloc ... Vergr"o"sern eines Speicherblocks (wobei 
+                                       der Inhalt eventuell an eine neue Position kommt)
+                       mem_usage ..... Menge des bereits belegten Speichers
+
+
+       2.   explizites Anfordern und automatisches Freigeben
+       
+                       dump_alloc .... Anfordern eines Speicherblocks vom
+                                       (wie ich es nenne) DUMP-Speicher
+                       dump_realloc .. Vergr"o"sern eines Speicherblocks
+                       dump_size ..... Merkt sich eine Freigabemarke am Dump
+                       dump_release .. Gibt allen Speicher, der nach der Marke angelegt 
+                                       worden ist, wieder frei.
+                                       
+       
+Es gibt f"ur diese Funktionen ein paar praktische Makros:
+
+       NEW (type) ....... legt Speicher f"ur ein Element des Typs `type` an.
+       FREE (ptr,type) .. gibt Speicher zur"uck
+       
+       MNEW (type,num) .. legt Speicher f"ur ein ganzes Array an
+       MFREE (ptr,type,num) .. gibt den Speicher wieder her
+       
+       MREALLOC (ptr,type,num1,num2) .. vergr"o"sert den Speicher f"ur das Array
+                                        auf die Gr"o"se num2
+                                        
+Die meisten der Makros gibt es auch f"ur den DUMP-Speicher, na"mlich mit
+gleichem Namen, nur mit vorangestelltem 'D', also:     
+       
+       DNEW,  DMNEW, DMREALLOC   (DFREE gibt es nat"urlich keines)
+
+
+-------------------------------------------------------------------------------
+
+Die restlichen Makros:
+
+       ALIGN (pos, size) ... Rundet den Wert von 'pos' auf die n"achste durch
+                             'size' teilbare Zahl auf.
+                             
+       
+       OFFSET (s,el) ....... Berechnet den Offset (in Bytes) des Elementes 'el'   
+                             in der Struktur 's'.
+                             
+       MCOPY (dest,src,type,num) ... Kopiert 'num' Elemente vom Typ 'type'.
+       
+
+*/
diff --git a/toolbox/tree.c b/toolbox/tree.c
new file mode 100644 (file)
index 0000000..ae74ffc
--- /dev/null
@@ -0,0 +1,166 @@
+/************************** toolbox/tree.c *************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Not documented, see tree.h.
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "memory.h"
+#include "tree.h"
+
+
+tree *tree_new (treeelementcomperator comperator)
+{
+       tree *t = NEW (tree);
+       
+       t -> usedump = 0;
+       t -> comperator = comperator;
+       t -> top = NULL;
+       t -> active = NULL;
+               
+       return t;
+}
+
+tree *tree_dnew (treeelementcomperator comperator)
+{
+       tree *t = DNEW (tree);
+       
+       t -> usedump = 1;
+       t -> comperator = comperator;
+       t -> top = NULL;
+       t -> active = NULL;
+       
+       return t;
+}
+
+
+static void tree_nodefree (treenode *tn)
+{
+       if (!tn) return;
+       tree_nodefree (tn -> left);
+       tree_nodefree (tn -> right);
+       FREE (tn, treenode);
+}
+
+void tree_free (tree *t)
+{
+       assert (! t -> usedump);
+       
+       tree_nodefree ( t -> top );
+       FREE (t, tree);
+}
+
+
+static treenode *tree_nodeadd 
+    (tree *t, treenode *par, treenode *n, void *element, void *key)
+{
+       if (!n) {
+               if ( t-> usedump )  n = DNEW (treenode);
+               else                n = NEW (treenode);
+               
+               n -> left = NULL;
+               n -> right = NULL;
+               n -> parent = par;
+               n -> element = element;
+               }
+       else {
+               if ( t->comperator (key, n -> element) < 0 ) {
+                       n -> left = tree_nodeadd (t, n, n -> left, element, key);
+                       }
+               else {
+                       n -> right = tree_nodeadd (t, n, n -> right, element, key);
+                       }
+               }
+               
+       return n;
+}
+
+void tree_add (tree *t, void *element, void *key)
+{
+       t -> top = tree_nodeadd (t, NULL, t -> top, element, key);
+       t -> active = t -> top;
+}
+
+
+static treenode *tree_nodefind (tree *t, treenode *n, void *key)
+{
+       int way;
+
+       if (!n) return NULL;
+
+       way = t -> comperator (key, n->element);
+       if (way==0) return n;
+       if (way<0) return tree_nodefind (t, n -> left, key);
+       else       return tree_nodefind (t, n -> right, key);
+}
+
+
+void *tree_find (tree *t, void *key)
+{
+       treenode *tn = tree_nodefind (t, t -> top, key);
+       if (!tn) return NULL;
+
+       t -> active = tn;
+       return tn -> element;
+}
+
+
+
+void *tree_this (tree *t)
+{      
+       if (! t->active) return NULL;
+       return t->active->element;
+}
+
+
+static treenode *leftmostnode(treenode *t)
+{
+       while (t->left) t=t->left;
+       return t;
+}
+
+void *tree_first (tree *t)
+{
+       treenode *a = t->top;
+       if (!a) return NULL;
+
+       a = leftmostnode (a);
+       t->active = a;
+       return a->element;
+}
+
+void *tree_next (tree *t)
+{
+       treenode *a = t->active;
+       treenode *comefrom = NULL;
+
+       while (a) {
+               if (!a) return NULL;
+
+               if (a->left && (a->left == comefrom)) {
+                       t -> active = a;
+                       return a->element;
+                       }
+       
+               if (a->right && (a->right != comefrom) ) {
+                       a = leftmostnode(a->right);
+                       t -> active = a;
+                       return a->element;
+                       }
+               
+               comefrom=a;
+               a=a->parent;
+               }
+       t->active = NULL;
+       return NULL;
+}
diff --git a/toolbox/tree.h b/toolbox/tree.h
new file mode 100644 (file)
index 0000000..fa974bb
--- /dev/null
@@ -0,0 +1,45 @@
+/************************* toolbox/tree.h **************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Verwaltung bin"arer B"aume 
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1996/10/03
+
+*******************************************************************************/
+
+typedef int (*treeelementcomperator) (void *key, void * element);
+
+
+typedef struct treenode {
+       struct treenode *left,*right;
+       struct treenode *parent;
+       
+       void *element;
+       } treenode;
+
+typedef struct {
+       int usedump;
+       treeelementcomperator comperator;       
+
+       treenode *top;
+       treenode *active;
+       } tree;
+
+
+
+tree *tree_new (treeelementcomperator comperator);
+tree *tree_dnew (treeelementcomperator comperator);
+void tree_free (tree *t);
+
+void tree_add (tree *t, void *element, void *key);
+void *tree_find (tree *t, void *key);
+
+void *tree_this (tree *t);
+void *tree_first (tree *t);
+void *tree_next (tree *t);
+