This is just a guess since I'm unfamiliar with the compiler and
haven't touched the processor since the 80s, but, off the top of my
head, this looks like an optimization to me. Does the value in rr2
get used in the instruction sequence following this? If so, it
probably means that a later statement or a part of the same state
operates on the same data.
ipc.ip_addr.l = *(unsigned long)(uap->addr.l)&0x7F00FFFF;
First off, I'm surprised that even an old compiler will dereference an
non pointer type and know what type of data is stored in the pointer.
The other issue breaking my brain is that you're making me recall that
the register order follows the memory order with r5 being the lower
order word of rr4. Ouch. Maybe my brain is getting too used to modern
conveniences...
Here's an overly complex interpretation of each instruction in more modern c.
/* 0006de: 35a2 0004 ldl rr2,rr10(#$0004) */
register unsigned long rr2=uap->addr.l;
/* 0006e2: 9424 ldl rr4,rr2 */
register unsigned long rr4=rr2;
/* 0006e4: 0704 7f00 and r4,#$7f00 */
rr4 &= 0x7f00ffff;
/* 0006e8: 5d04 8000 0004 ldl $8000+$0x4,rr4 */
ipc.ip_addr.l = rr4;
Which means that rr2 still contains uap->addr.l;
So I would guess this line is
ipc.ip_addr.l = uap->addr.l & 0x7f00ffff;
and the following line is...
something_else = {some other operation on uap->addr.l} ;
Seems like something an 80s era peephole optimizer would do if it
could guarantee that uap != &ipc. Once an optimizer gets involved,
recovering the original code can get difficult and you may need to
settle for functional equivalents.
Another possibility is that the original code was something like this,
ipc.ip_addr.l = ( another_variable = uap ->addr.l ) & 0x7f00ffff;
although I can't imagine why someone would write this. (And the
compiler would need to guarantee that "another_variable" and
ipc.ip_addr.l were not the same thing (i.e. another_variable is an
actual variable and not a dereferenced pointer).
Eric
On Sat, May 31, 2008 at 4:00 AM, Oliver Lehmann <lehmann at ans-netz.de> wrote:
Hi,
As I promissed here comes my first question ;)
While writing several C files for the WEGA/ZEUS kernel out of the
disassembled objects (with unresolved symbols marked as external) I came
across a piece of code I can't get to reproduce when compiling C.
The original object contains:
0006de: 35a2 0004 ldl rr2,rr10(#$0004)
0006e2: 9424 ldl rr4,rr2
0006e4: 0704 7f00 and r4,#$7f00
0006e8: 5d04 8000 0004 ldl $8000+$0x4,rr4
I tried to reproduce it:
ipc.ip_addr.l = *(unsigned long)(uap->addr.l)&0x7F00FFFF;
Which generates:
0008 35a2 0004 59 ldl rr2,rr10(#4)
000c 0702 7f00 60 and r2,#32512
0010 5d02 8000* 61 ldl _ipc+4,rr2
0014 0004*
which looks for me functional the same...
I also tried:
ipc.ip_addr.l = *(unsigned long *)(uap->addr.l)&0x7F00FFFF;
Which generates:
0010 35a2 0004 60 ldl rr2,rr10(#4)
0014 1424 61 ldl rr4, at rr2
0016 0704 7f00 62 and r4,#32512
001a 5d04 8000* 63 ldl _ipc+4,rr4
Which looks "better" but isn't the same as the original because the
adress of rr2 gets loaded into rr4 first, not rr2 itself.
I'm a bit lost because I tried several different */&-pointer stuff to get
this as it is in the original object without success. the elements
ip_addr and addr are both of type saddr_t which is declare as follows:
typedef union
{
caddr_t l;
struct
{
unsigned left;
unsigned right;
} half;
} saddr_t; /* segmented address with parts */
rr4 itself gets later overwritten in both codes - my code and the
original object - it is not reserved for an internal C-variable. Maybe
someone from you can help me here?
--
Oliver Lehmann
http://www.pofo.de/
http://wishlist.ans-netz.de/