|
From: <sv...@va...> - 2006-03-01 18:58:46
|
Author: sewardj
Date: 2006-03-01 18:58:39 +0000 (Wed, 01 Mar 2006)
New Revision: 1579
Log:
Implement mtocrf/mfocrf.
Modified:
trunk/priv/guest-ppc/toIR.c
Modified: trunk/priv/guest-ppc/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-ppc/toIR.c 2006-02-24 00:14:29 UTC (rev 1578)
+++ trunk/priv/guest-ppc/toIR.c 2006-03-01 18:58:39 UTC (rev 1579)
@@ -5232,16 +5232,26 @@
break;
}
=20
- case 0x013: // mfcr (Move from Cond Register, PPC32 p467)
- if (b11to20 !=3D 0) {
- vex_printf("dis_proc_ctl(ppc)(mfcr,b11to20)\n");
- return False;
+ case 0x013:=20
+ // b11to20=3D=3D0: mfcr (Move from Cond Register, PPC32 p467)
+ // b20=3D=3D1 & b11=3D=3D0: mfocrf (Move from One CR Field)
+ // However it seems that the 'mfcr' behaviour is an acceptable
+ // implementation of mfocr (from the 2.02 arch spec)
+ if (b11to20 =3D=3D 0) {
+ DIP("mfcr r%u\n", rD_addr);
+ putIReg( rD_addr, mkSzWiden32(ty, getGST( PPC_GST_CR ),
+ /* Signed */False) );
+ break;
}
- DIP("mfcr r%u\n", rD_addr);
- putIReg( rD_addr, mkSzWiden32(ty, getGST( PPC_GST_CR ),
- /* Signed */False) );
- break;
- =20
+ if (b20 =3D=3D 1 && b11 =3D=3D 0) {
+ DIP("mfocrf r%u,%u\n", rD_addr, CRM);
+ putIReg( rD_addr, mkSzWiden32(ty, getGST( PPC_GST_CR ),
+ /* Signed */False) );
+ break;
+ }
+ /* not decodable */
+ return False;
+ =20
/* XFX-Form */
case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
=20
@@ -5301,14 +5311,27 @@
break;
}
=20
- case 0x090: { // mtcrf (Move to Cond Register Fields, PPC32 p477)
+ case 0x090: {=20
+ // b20=3D=3D0: mtcrf (Move to Cond Register Fields, PPC32 p477)
+ // b20=3D=3D1: mtocrf (Move to One Cond Reg Field)
Int cr;
UChar shft;
- if (b11 !=3D 0 || b20 !=3D 0) {
- vex_printf("dis_proc_ctl(ppc)(mtcrf,b11|b20)\n");
+ if (b11 !=3D 0)
return False;
+ if (b20 =3D=3D 1) {
+ /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
+ 1 field is written. It seems more robust to decline to
+ decode the insn if so. */
+ switch (CRM) {
+ case 0x01: case 0x02: case 0x04: case 0x08:
+ case 0x10: case 0x20: case 0x40: case 0x80:
+ break;
+ default:=20
+ return False;=20
+ }
}
- DIP("mtcrf 0x%x,r%u\n", CRM, rS_addr);
+ DIP("%s 0x%x,r%u\n", b20=3D=3D1 ? "mtocrf" : "mtcrf",=20
+ CRM, rS_addr);
/* Write to each field specified by CRM */
for (cr =3D 0; cr < 8; cr++) {
if ((CRM & (1 << (7-cr))) =3D=3D 0)
|