On Sun, 29 Jun 2008 10:25:23 +0200
Oliver Lehmann <lehmann(a)ans-netz.de> wrote:
Jose R. Valverde wrote:
Why don't you try to split the assignment
into various statements
to reproduce the assembly and the recombine them? Like, e.g.
1: r2 = uap->linkname; /* ldl rr2,rr8(#4) */
2: r4 = (long) r2; /* ldl rr4,rr2 */
3: r4 &= 0x7F00FFFF; /* and rr4,#32512 */
4: u.u_dirp.l = (caddr_t) r4; /* ldl _u+78, rr4 */
hm.. this won't work because the compiler starts handing out registers
the register-declared variables with the highest register possible so
would start with rr10 or so.
But you would still be able to see what did generate the code (barring
register number).
u.u_dirp.l = (caddr_t) ((long) (((saddr_t)
uap->linkname).l) & 0x7F00FFFF);
I've changed it to:
u.u_dirp.l = (caddr_t) ((long) (((saddr_t *) uap->linkname)->l) &
0x7F00FFFF);
otherwise it won't compile. It compiles to:
ldl rr2,rr8(#4)
ldl rr4,@rr2
and r4,#32512
ldl _u+78,rr4
is it because I added a * and changed . to ->?
Yes, but it also does not reflect the correct usage. linkname is not an saddr_t* but
an saddrt_t. And you want to assign directly the value of uap->linkname not what it
points to.
typedef union
{
caddr_t l;
struct
{
unsigned left;
unsigned right;
} half;
} saddr_t; /* segmented address with parts */
u.u_dirp = (saddr_t) (((long) uap->linkname)
& 0x7F00FFFF);
this generates:
"sys2.c":305: operands of CAST have incompatible types
"sys2.c":305: operands of "=" have incompatible types
:(
My fault. That's a typical beginner's mistake I made there. I'm starting
to feel embarrassed of so many mistakes I'm making lately. BTW, I'm on a
deadline so most probably my mind is not 100% in place so do not take me
too seriously specially when dealing with complex abstract data types.
That is because an saddr_t is a union. You cannot assign directly to a
union (u.u_dirp), you must assign to a union member (u.u_dirp.l), but
the union member is not an saddr_t, it is a caddr_t: the correct text
would be
u.u_dirp.l = (caddr_t) (((long) uap->linkname) & 0x7F00FFFF);
which you know does not work. That is why I suggested the extra cast to
see if the compiler would be misled into using an unneeded zero-offset
assignment instruction to an auxiliary register.
u.u_dirp.l = (caddr_t) ((long) (((saddr_t) uap->linkname).l) & 0x7F00FFFF);
that should be tantamount to
u.u_dirp.l = (caddrt_t) ((long) ((caddr_t) uap->linkname) & 0x7F00FFFF);
where due to the long cast the initial caddr_t cast would be redundant
reducing to
u.u_dirp.l = (caddr_t) ((long) uap->linkname & 0x7F00FFFF);
but introducing a saddr_t cast that might fool the compiler into a
temporary assignment with a zero offset (the .l) into ldl rr4,rr2
And I still think that dividing the assignment into intermediate
instructions and looking at the assembly might shed some light into
what is going on.
--
These opinions are mine and only mine. Hey man, I saw them first!
José R. Valverde
De nada sirve la Inteligencia Artificial cuando falta la Natural