|
From: Cerion Armour-B. <ce...@op...> - 2006-05-03 16:02:43
|
On Wednesday 03 May 2006 17:16, Randy Macleod wrote:
> If I run objdump on my test program, I see that the instruction is:
> 10001d24: 7d 20 4e 2c lhbrx r9,r0,r9
>
...
> So, I tried to hack in support for lhbrx:
>
> [VEX]$ ls ./priv/guest-ppc32/toIR.c*
> ./priv/guest-ppc32/toIR.c ./priv/guest-ppc32/toIR.c.orig
> [VEX]$ diff ./priv/guest-ppc32/toIR.c*
> 2612,2618c2612
> < case 0x62C: // lhbrx (Load HW, Byte-Reverse Indexed)
> < DIP("lwzx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
> < vex_printf("rwm: fixed lhbrx?....\n");
> < // ?? rwm: putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA_reg)) );
> < putIReg( rD_addr, unop(Iop_16Uto32,
> < loadBE(Ity_I16, mkexpr(EA_reg))) );
> < break;
> ---
>
> 7261,7263d7254
> < case 0x62C: // lhbrx
> < if (dis_int_load( theInstr )) goto decode_success;
> < goto decode_failure;
>
>
> but I don't really understand valgrind's design. Does my put putIReg call
> look right? I'm reading the manual and docs/internals now...
Getting there, but not quite... this insn does this (numbers are bytes, -'s
are cleared bytes)
[3|2|1|0] -> [-|-|2|3]
This insn was implemented a while back, but not tested... Take a look at
toIR.c:5126 from the trunk:
//zz case 0x316: // lhbrx (Load Half Word Byte-Reverse Indexed, PPC32 p449)
//zz vassert(0);
//zz
//zz DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
//zz assign( byte0, loadBE(Ity_I8, mkexpr(EA)) );
//zz assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32
(1))) );
//zz assign( rD, binop(Iop_Or32,
//zz binop(Iop_Shl32, mkexpr(byte1), mkU8(8)),
//zz mkexpr(byte0)) );
//zz putIReg( rD_addr, mkexpr(rD));
//zz break;
Looks like it'll work, but not very nice, what with two loads... perhaps
something like this might do better (just a thought - not tested):
case 0x316: // lhbrx (Load Half Word Byte-Reverse Indexed, PPC32 p449)
DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
assign( w2, binop(Iop_Or32,
binop(Iop_And32, mkU32(0x0000FF00),
binop(Iop_Shr32, mkexpr(w1), mkU8(8))),
binop(Iop_Shr32, mkexpr(w1), mkU8(24))
) );
putIReg( rD_addr, mkSzWiden32(ty, mkexpr(w2),
/* Signed */False) );
break;
Hope that gets you started.
btw, the reason I get to opcode 0x316 (not 0x62C) is because opc2 here doesn't
include bit0:
/* Extract 10-bit secondary opcode, instr[10:1] */
static UInt ifieldOPClo10 ( UInt instr) {
return IFIELD( instr, 1, 10 );
}
If you felt like going further and hacking up a test for this insn (something
similar to lwbrx, I guess) , it'll get added much more quickly!
Cerion
|