kaffe on Alpha

Dirk Grunwald grunwald at pa.dec.com
Mon Oct 19 17:16:57 PDT 1998


I'm suprised that the old sysdepCallMethod for the Alpha ever actually
worked - I'm attaching something that I think is correct, however, I'm
still not able to get Kaffe running in interpreter mode.

The problem was/is that when you compile using -O, the stack storage
layout convention changes. With low optimization (e.g., -O0), the FP
register $15 points to the top of the frame, and SP points to bottom.
Using GCC, storage near the bottom is "free" - i.e., you allocate a
large array, it's next to the address pointed to by 'SP'.

The old call code depended on this by allocating a large array,
sticking arguments into there, setting the SP to the end of that array
and doing a JSR.

If you compile with -O, there is no FP. Storage immediately above the
SP is now used to hold the spill for the callee-saved registers (S0
etc). Thus, if you use the old solution, you'll stomp over the callee
saved registers (leading to death).

Moreover, a small number of arguments are shoved into registers for
argument passing. Since the argument registers were not marked as
being used in the procedure, assignments to them were silently
dead-code eliminated. This meant that with -O optimization those
registers (a0..a5) really didn't contain any meaningful values.

In looking at other ports (e.g., ARM), it appears that this (marking
those registers as used) has been fixed in some machine definitions.

I'm including my current "common.h". I believe this should fix the
problems I mentioned, but I'm still running into problems. In
particular..

>> Loading java/io/DataOutput.class(/udir/grunwald/.alpha/share/kaffe/Klasses.jar) [compressed]
>> Method = java/lang/System.initProperties(Ljava/util/Properties;)Ljava/util/Properties;
>> Native stub = 'java_lang_System_initProperties'
>> Unaligned access pid=31780 <Kaffe> va=0x140018304 pc=0x120052914 ra=0x1200528f4 inst=0xa45d8448
>> 
>> Program received signal SIGSEGV, Segmentation fault.
>> 0x12005291c in virtualMachine (meth=0x1400a37b8, arg=0x11fffec48, retval=0x11fffee48, tid=0x140076cd8)
>>     at kaffe.def:2276

I'm not certain what the problem is and probably won't fix it
today. If someone else is poking at the Alpha port, I'd appreciate
hearing about it to coordinate efforts.

/*
 * alpha/common.h
 * Common Alpha configuration information.
 *
 * Copyright (c) 1996, 1997
 *	Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution 
 * of this file. 
 *
 * 15 July, 1998:
 *      Modified by Rick Greer (rick at sandpiper.com) for use with Alpha Linux
 */

#ifndef __alpha_common_h
#define __alpha_common_h

/*
 * Make a call to a native or Java (JIT) method.
 *  This assembly code should build a standard C call using the passed
 *  call information.  By its nature this is highly processor specific.
 *  This function is mandatory for the JIT, but can be avoided for
 *  the interpreter if you don't define NO_KAFFE_STUBS.  However, the
 *  Kaffe stubs will be deprecated at some time in the future and
 *  this function will be needed for JNI support when it comes.
 */
#define	NO_KAFFE_STUBS

#define getJavaArg(CALL, n)						      \
(   /*									      \
     *  Sign-extend short arguments:					      \
     *									      \
     *  This macro sign extends short (i.e, 32-bit or less) arguments to a    \
     *  64-bit "long" that can be inserted directly into a 64-bit register.   \
     */									      \
									      \
    ((CALL)->callsize[n] == 2) ? (CALL)->args[n].j : (long)((CALL)->args[n].i)\
)

#define	sysdepCallMethod(CALL)						      \
{   /*									      \
     *  Call a Java Method:						      \
     *									      \
     *  This macro generates an in-line call to the Java method described by  \
     *  the given method info structure ("CALL" argument) and stores the      \
     *  return value in the info struct as well.			      \
     */									      \
									      \
    int x, rags = 0;		    					      \
	/* The parameter registers ... 					    */\
        register long r16 asm("$16");					      \
        register long r17 asm("$17");					      \
        register long r18 asm("$18");					      \
        register long r19 asm("$19");					      \
        register long r20 asm("$20");					      \
        register long r21 asm("$21");					      \
    register unsigned long *sp asm("$30");                                    \
    register unsigned long *osp asm("$9"); \
    /* any temporary register would do.. */  \
    register unsigned long *nsp = sp; \
    osp = sp; \
									      \
    for (x = 0; x < (CALL)->nrargs; x++)				      \
    {   /*								      \
         *  The alpha has 64-bit registers, so we don't really need the ex-   \
         *  tra "callsize = 0" entries in the arg list.  This loop removes    \
         *  them by sliding any subsequent entries to the left.		      \
         */								      \
									      \
        if ((CALL)->callsize[x] > 0)					      \
        {								      \
            if (x > rags) (CALL)->args[rags] = (CALL)->args[x];		      \
            rags += 1;							      \
        }								      \
    }									      \
									      \
    {                                                                         \
									      \
    switch (rags)							      \
    {                                                                         \
        default:							      \
	  {									\
        /*		                                                              \
         * We're doing to hack the frame buffer the difficult way..               \
         */                                                                       \
        int margs = rags - 6;        \
        nsp = sp - margs;  \
	/* Copy arguments to the stack we allocated */			      \
	  for (x = 0; x < margs; x++) {						\
	    nsp[x] = getJavaArg(CALL, x+6);					\
	  }									\
        }								      \
									      \
        /* The first 6 arguments are loaded into the parameter registers.   */\
        case 6: r21 = getJavaArg(CALL, 5);				      \
        case 5: r20 = getJavaArg(CALL, 4);				      \
        case 4: r19 = getJavaArg(CALL, 3);				      \
        case 3: r18 = getJavaArg(CALL, 2);				      \
        case 2: r17 = getJavaArg(CALL, 1);				      \
        case 1: r16 = getJavaArg(CALL, 0);				      \
        case 0:  /* nothing */ \
    }									      \
    asm("mov %2,$27\n\
	 mov %0,$30\n\
         jsr $26,($27),0 \n\
	 mov %1, $30\n\
         ldgp $29,0($26) \n\
	 "  :: "r" (nsp), "r" (osp), "r" ((CALL)->function), \
	/* include all the argument registers least they get DCE'd away */   \
	"r" (r16), "r" (r17), "r" (r18), "r" (r19), "r" (r20), "r" (r21) \
	/* and mention that we kill these.. */   \
	: "$27", "$26"); \
    }									      \
    asm("stq $0,%0" : "=m" ((CALL)->ret->j));				      \
									      \
    /* Store floating point return value over (default) integer value ...   */\
    if ((CALL)->rettype == 'D') asm("stt $f0,%0" : "=m" ((CALL)->ret->d));    \
    if ((CALL)->rettype == 'F') asm("sts $f0,%0" : "=m" ((CALL)->ret->f));    \
}



#endif



More information about the kaffe mailing list