FIX: floating point values not returned correctly on the ARM
Dirk Grunwald
grunwald at pa.dec.com
Sun Jan 3 17:11:07 PST 1999
I noticed this problem while trying to determine why my pop up menus
are causing me to core dump (still...stupid missing symbol, I think).
The following tests failed...
class domath{
public static void main (String args[]) {
System.out.println("Hello World!");
System.out.println("Sqrt(10) is " + java.lang.Math.sqrt(10));
System.out.println("sin(10) is " + java.lang.Math.sin(10));
}
}
also, when you run "TestNative" from the regression directory, it
fails as well. There's still one anomoly that I haven't figured out in
with TestNative (actually, a modified JNI version). The last test
d = test16floatdouble(
-1.2f, 0.2, 3.3, 4.5, 5.6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
returns
j = 10.00
k = 0.00
l = 12.00
m = 13.00
n = 14.00
o = 15.00
p = 16.00
test16floatdouble returned 120.40000282
Notice that "k = 0.00", rather than "k = 11.0" as expected. I have no
idea why this would occur -- it's way past the point of the special
cases for the first four arguments, which are passed in registers.
The following version of "arm/common.h" should fix it. The primary fix
is adding the floating point store's at the end of the function.
//-*-c++-*-
#ifndef _arm_common_h_
#define _arm_common_h_
/*
* arm/common.h
* ARM common 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.
*/
/* The ARM we never align to more than a 4 byte boundary. */
#define ALIGNMENT_OF_SIZE(S) ((S) < 4 ? (S) : 4)
/*
* The calling convention is such that the first four 32bit values are
* passed in r0-r3, and the remainder goes on the stack.
* Floating point values are passed in integer registers.
*
* This machine is a little endian machine, but double floating point
* values are stored in big endian *word* order. Note that we do not
* have to take this into account here. It is a convention of the
* software floating point libraries and the build tools.
*/
#define sysdepCallMethod(CALL) do { \
int nrargs = (CALL) -> nrargs; \
int i; \
register double f0 asm("f0"); \
register int r0 asm("r0"); \
register int r1 asm("r1"); \
register int r2 asm("r2"); \
register int r3 asm("r3"); \
register unsigned long *nsp; \
register unsigned long *osp; \
int *res; \
if (0) {\
fprintf(stderr,"Call with %d args\n", nrargs); \
for (i = 0; i < nrargs; i++) { \
fprintf(stderr,"Arg %d size %d = %p\n", i, ((CALL) -> callsize[i]), ((CALL)->args[i])); \
}\
}\
asm __volatile__("mov %0, sp" : "=r" (osp)); \
nsp = (nrargs > 3) ? osp - ((nrargs-3) * 2) : osp ;\
switch(nrargs) { \
default: \
{ \
int *args = nsp; \
int argidx = 4; \
if ((CALL)->callsize[3] == 2) args++; \
for(; argidx < (CALL)->nrargs; ++argidx) { \
if ((CALL)->callsize[argidx]) { \
*args++ = (CALL)->args[argidx].i; \
if ((CALL)->callsize[argidx] == 2) \
*args++ = ((CALL)->args[argidx].j) >> 32; \
} \
} \
} \
/* Fall through ... */ \
case 4: \
if ((CALL)->callsize[3]) { \
r3 = (CALL)->args[3].i; \
if ((CALL)->callsize[3] == 2) { \
nsp[0] = ((CALL)->args[3].j) >> 32; \
} \
} \
/* Fall through ... */ \
case 3: \
if ((CALL)->callsize[2]) { \
r2 = (CALL)->args[2].i; \
if ((CALL)->callsize[2] == 2) { \
r3 = ((CALL)->args[2].j) >> 32; \
} \
} \
/* Fall through ... */ \
case 2: \
if ((CALL)->callsize[1]) { \
r1 = (CALL)->args[1].i; \
if ((CALL)->callsize[1] == 2) { \
r2 = ((CALL)->args[1].j) >> 32; \
} \
} \
/* Fall through ... */ \
case 1: \
if ((CALL)->callsize[0]) { \
r0 = (CALL)->args[0].i; \
if ((CALL)->callsize[0] == 2) { \
r1 = ((CALL)->args[0].j) >> 32; \
} \
} \
/* Fall through ... */ \
case 0: \
asm ("\n\
mov sp, %4\n\
mov lr, pc\n\
mov pc, %3\n\
mov %5, sp\n"\
: "=r" (r0), "=r" (r1), "=f" (f0) \
: "r" ((CALL)->function), "r" (nsp), "r" (osp), \
"0" (r0), "1" (r1), "r" (r2), "r" (r3) \
: "sp","ip", "rfp", "sl", "fp", "lr" \
); \
res = (int *)(CALL)->ret; \
res[0] = r0; \
res[1] = r1; \
/* Store floating point return value over (default) integer value ... */\
if ((CALL)->rettype == 'D') asm("stfd %1,%0" : "=m" ((CALL)->ret->d) : "f" (f0)); \
if ((CALL)->rettype == 'F') asm("stfs %1,%0" : "=m" ((CALL)->ret->f) : "f" (f0)); \
break; \
} \
} while (0) \
typedef struct _machineStackFrame {
void* ret_fp;
void* ret_sp;
void* ret_pc;
} machineStackFrame;
#define NF(F) ((F)-1)
#define STACK_FRAME(F) (NF(F)->ret_fp)
#define STACK_PC(F) (NF(F)->ret_pc)
#define STACK_CURRENT_FRAME() ({ void* v ; asm volatile("mov %0,fp" : "=r" (v)) ; v; })
/*
* The ARM is odd - doubles are stored big endian even when the machine
* is little endian.
*/
#define DOUBLE_WORDS_BIG_ENDIAN 1
#endif
More information about the kaffe
mailing list