[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Libffi (git master) and guile (git master) on MIPS n32
From: |
rixed |
Subject: |
Re: Libffi (git master) and guile (git master) on MIPS n32 |
Date: |
Tue, 8 Feb 2011 08:48:06 +0100 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
-[ Mon, Feb 07, 2011 at 01:58:07PM -0800, Andrew Pinski ]----
> > The problem is : of these 64 bits, only the 32 lowest bits were set by
> > guile, and the upper 32 are desperately random.
>
> How were those lower 32bits set? If set by the 32bit instructions
> then it is automatically sign extended. If not then there is a bug in
> how guile is doing the returns
These lowest 32bits were set by guile's foreign.c/unpack function, using
this:
// called with type = ffi_cif->rtype of course, and loc = return value address
unpack (const ffi_type *type, void *loc, SCM x)
{
switch (type->type)
{
(...)
case FFI_TYPE_SINT32:
*(scm_t_int32 *) loc = scm_to_int32 (x);
break;
(...)
}
}
(note: this cast of an lvalue is not legal C but that's another story)
AFAICT, Guile is not tell how much data it should write, so it must resort
on rtype->type.
> Unless you have a bug somewhere in which you are using a non sign
> extended value with the 32bit instructions which then it becomes
> undefined at what the value of those instructions do (could be either
> treating it as a 64bit value, or do a sign extend or even put
> 0xDEADBEEFDEADBEEF in the register which is what the Octeon simulators
> do).
Sorry I do not understand this. Let's take a concrete exemple : guile
comparison function returns -1 to qsort. So it writes -1 on the return
value location (as a 32 bits value) with the code given above. This
location, which 32 upper bits were random (but positive) now looks like
this quad-word (this is a little endian mips) :
0x7fff09c0: 0xFF 0xFF 0xFF 0xFF 0x78 0x56 0x34 0x12
Now libffi loads this value into v0 :
ffi_closure_N32:
(...)
# Return flags are in v0
bne v0, FFI_TYPE_SINT32, cls_retint # v0 = FFI_TYPE_INT here, from the
flags
lw v0, V0_OFF2($sp)
(...)
cls_retint:
bne v0, FFI_TYPE_INT, cls_retfloat
ld v0, V0_OFF2($sp) # now v0 = 0x12345678FFFFFFFF
b cls_epilogue
And now we are back to the libc qsort, which will certainly compare v0
with 0 and see it's positive.