-[ 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.