3097 lines
118 KiB
Diff
3097 lines
118 KiB
Diff
|
Index: VEX/priv/guest_ppc_helpers.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/guest_ppc_helpers.c.orig
|
||
|
+++ VEX/priv/guest_ppc_helpers.c
|
||
|
@@ -385,74 +385,74 @@ void LibVEX_GuestPPC32_initialise ( /*OU
|
||
|
vex_state->guest_GPR30 = 0;
|
||
|
vex_state->guest_GPR31 = 0;
|
||
|
|
||
|
- vex_state->guest_FPR0 = 0;
|
||
|
- vex_state->guest_FPR1 = 0;
|
||
|
- vex_state->guest_FPR2 = 0;
|
||
|
- vex_state->guest_FPR3 = 0;
|
||
|
- vex_state->guest_FPR4 = 0;
|
||
|
- vex_state->guest_FPR5 = 0;
|
||
|
- vex_state->guest_FPR6 = 0;
|
||
|
- vex_state->guest_FPR7 = 0;
|
||
|
- vex_state->guest_FPR8 = 0;
|
||
|
- vex_state->guest_FPR9 = 0;
|
||
|
- vex_state->guest_FPR10 = 0;
|
||
|
- vex_state->guest_FPR11 = 0;
|
||
|
- vex_state->guest_FPR12 = 0;
|
||
|
- vex_state->guest_FPR13 = 0;
|
||
|
- vex_state->guest_FPR14 = 0;
|
||
|
- vex_state->guest_FPR15 = 0;
|
||
|
- vex_state->guest_FPR16 = 0;
|
||
|
- vex_state->guest_FPR17 = 0;
|
||
|
- vex_state->guest_FPR18 = 0;
|
||
|
- vex_state->guest_FPR19 = 0;
|
||
|
- vex_state->guest_FPR20 = 0;
|
||
|
- vex_state->guest_FPR21 = 0;
|
||
|
- vex_state->guest_FPR22 = 0;
|
||
|
- vex_state->guest_FPR23 = 0;
|
||
|
- vex_state->guest_FPR24 = 0;
|
||
|
- vex_state->guest_FPR25 = 0;
|
||
|
- vex_state->guest_FPR26 = 0;
|
||
|
- vex_state->guest_FPR27 = 0;
|
||
|
- vex_state->guest_FPR28 = 0;
|
||
|
- vex_state->guest_FPR29 = 0;
|
||
|
- vex_state->guest_FPR30 = 0;
|
||
|
- vex_state->guest_FPR31 = 0;
|
||
|
|
||
|
/* Initialise the vector state. */
|
||
|
# define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
|
||
|
|
||
|
- VECZERO(vex_state->guest_VR0 );
|
||
|
- VECZERO(vex_state->guest_VR1 );
|
||
|
- VECZERO(vex_state->guest_VR2 );
|
||
|
- VECZERO(vex_state->guest_VR3 );
|
||
|
- VECZERO(vex_state->guest_VR4 );
|
||
|
- VECZERO(vex_state->guest_VR5 );
|
||
|
- VECZERO(vex_state->guest_VR6 );
|
||
|
- VECZERO(vex_state->guest_VR7 );
|
||
|
- VECZERO(vex_state->guest_VR8 );
|
||
|
- VECZERO(vex_state->guest_VR9 );
|
||
|
- VECZERO(vex_state->guest_VR10);
|
||
|
- VECZERO(vex_state->guest_VR11);
|
||
|
- VECZERO(vex_state->guest_VR12);
|
||
|
- VECZERO(vex_state->guest_VR13);
|
||
|
- VECZERO(vex_state->guest_VR14);
|
||
|
- VECZERO(vex_state->guest_VR15);
|
||
|
- VECZERO(vex_state->guest_VR16);
|
||
|
- VECZERO(vex_state->guest_VR17);
|
||
|
- VECZERO(vex_state->guest_VR18);
|
||
|
- VECZERO(vex_state->guest_VR19);
|
||
|
- VECZERO(vex_state->guest_VR20);
|
||
|
- VECZERO(vex_state->guest_VR21);
|
||
|
- VECZERO(vex_state->guest_VR22);
|
||
|
- VECZERO(vex_state->guest_VR23);
|
||
|
- VECZERO(vex_state->guest_VR24);
|
||
|
- VECZERO(vex_state->guest_VR25);
|
||
|
- VECZERO(vex_state->guest_VR26);
|
||
|
- VECZERO(vex_state->guest_VR27);
|
||
|
- VECZERO(vex_state->guest_VR28);
|
||
|
- VECZERO(vex_state->guest_VR29);
|
||
|
- VECZERO(vex_state->guest_VR30);
|
||
|
- VECZERO(vex_state->guest_VR31);
|
||
|
+ VECZERO(vex_state->guest_VSR0 );
|
||
|
+ VECZERO(vex_state->guest_VSR1 );
|
||
|
+ VECZERO(vex_state->guest_VSR2 );
|
||
|
+ VECZERO(vex_state->guest_VSR3 );
|
||
|
+ VECZERO(vex_state->guest_VSR4 );
|
||
|
+ VECZERO(vex_state->guest_VSR5 );
|
||
|
+ VECZERO(vex_state->guest_VSR6 );
|
||
|
+ VECZERO(vex_state->guest_VSR7 );
|
||
|
+ VECZERO(vex_state->guest_VSR8 );
|
||
|
+ VECZERO(vex_state->guest_VSR9 );
|
||
|
+ VECZERO(vex_state->guest_VSR10);
|
||
|
+ VECZERO(vex_state->guest_VSR11);
|
||
|
+ VECZERO(vex_state->guest_VSR12);
|
||
|
+ VECZERO(vex_state->guest_VSR13);
|
||
|
+ VECZERO(vex_state->guest_VSR14);
|
||
|
+ VECZERO(vex_state->guest_VSR15);
|
||
|
+ VECZERO(vex_state->guest_VSR16);
|
||
|
+ VECZERO(vex_state->guest_VSR17);
|
||
|
+ VECZERO(vex_state->guest_VSR18);
|
||
|
+ VECZERO(vex_state->guest_VSR19);
|
||
|
+ VECZERO(vex_state->guest_VSR20);
|
||
|
+ VECZERO(vex_state->guest_VSR21);
|
||
|
+ VECZERO(vex_state->guest_VSR22);
|
||
|
+ VECZERO(vex_state->guest_VSR23);
|
||
|
+ VECZERO(vex_state->guest_VSR24);
|
||
|
+ VECZERO(vex_state->guest_VSR25);
|
||
|
+ VECZERO(vex_state->guest_VSR26);
|
||
|
+ VECZERO(vex_state->guest_VSR27);
|
||
|
+ VECZERO(vex_state->guest_VSR28);
|
||
|
+ VECZERO(vex_state->guest_VSR29);
|
||
|
+ VECZERO(vex_state->guest_VSR30);
|
||
|
+ VECZERO(vex_state->guest_VSR31);
|
||
|
+ VECZERO(vex_state->guest_VSR32);
|
||
|
+ VECZERO(vex_state->guest_VSR33);
|
||
|
+ VECZERO(vex_state->guest_VSR34);
|
||
|
+ VECZERO(vex_state->guest_VSR35);
|
||
|
+ VECZERO(vex_state->guest_VSR36);
|
||
|
+ VECZERO(vex_state->guest_VSR37);
|
||
|
+ VECZERO(vex_state->guest_VSR38);
|
||
|
+ VECZERO(vex_state->guest_VSR39);
|
||
|
+ VECZERO(vex_state->guest_VSR40);
|
||
|
+ VECZERO(vex_state->guest_VSR41);
|
||
|
+ VECZERO(vex_state->guest_VSR42);
|
||
|
+ VECZERO(vex_state->guest_VSR43);
|
||
|
+ VECZERO(vex_state->guest_VSR44);
|
||
|
+ VECZERO(vex_state->guest_VSR45);
|
||
|
+ VECZERO(vex_state->guest_VSR46);
|
||
|
+ VECZERO(vex_state->guest_VSR47);
|
||
|
+ VECZERO(vex_state->guest_VSR48);
|
||
|
+ VECZERO(vex_state->guest_VSR49);
|
||
|
+ VECZERO(vex_state->guest_VSR50);
|
||
|
+ VECZERO(vex_state->guest_VSR51);
|
||
|
+ VECZERO(vex_state->guest_VSR52);
|
||
|
+ VECZERO(vex_state->guest_VSR53);
|
||
|
+ VECZERO(vex_state->guest_VSR54);
|
||
|
+ VECZERO(vex_state->guest_VSR55);
|
||
|
+ VECZERO(vex_state->guest_VSR56);
|
||
|
+ VECZERO(vex_state->guest_VSR57);
|
||
|
+ VECZERO(vex_state->guest_VSR58);
|
||
|
+ VECZERO(vex_state->guest_VSR59);
|
||
|
+ VECZERO(vex_state->guest_VSR60);
|
||
|
+ VECZERO(vex_state->guest_VSR61);
|
||
|
+ VECZERO(vex_state->guest_VSR62);
|
||
|
+ VECZERO(vex_state->guest_VSR63);
|
||
|
|
||
|
# undef VECZERO
|
||
|
|
||
|
@@ -542,74 +542,73 @@ void LibVEX_GuestPPC64_initialise ( /*OU
|
||
|
vex_state->guest_GPR30 = 0;
|
||
|
vex_state->guest_GPR31 = 0;
|
||
|
|
||
|
- vex_state->guest_FPR0 = 0;
|
||
|
- vex_state->guest_FPR1 = 0;
|
||
|
- vex_state->guest_FPR2 = 0;
|
||
|
- vex_state->guest_FPR3 = 0;
|
||
|
- vex_state->guest_FPR4 = 0;
|
||
|
- vex_state->guest_FPR5 = 0;
|
||
|
- vex_state->guest_FPR6 = 0;
|
||
|
- vex_state->guest_FPR7 = 0;
|
||
|
- vex_state->guest_FPR8 = 0;
|
||
|
- vex_state->guest_FPR9 = 0;
|
||
|
- vex_state->guest_FPR10 = 0;
|
||
|
- vex_state->guest_FPR11 = 0;
|
||
|
- vex_state->guest_FPR12 = 0;
|
||
|
- vex_state->guest_FPR13 = 0;
|
||
|
- vex_state->guest_FPR14 = 0;
|
||
|
- vex_state->guest_FPR15 = 0;
|
||
|
- vex_state->guest_FPR16 = 0;
|
||
|
- vex_state->guest_FPR17 = 0;
|
||
|
- vex_state->guest_FPR18 = 0;
|
||
|
- vex_state->guest_FPR19 = 0;
|
||
|
- vex_state->guest_FPR20 = 0;
|
||
|
- vex_state->guest_FPR21 = 0;
|
||
|
- vex_state->guest_FPR22 = 0;
|
||
|
- vex_state->guest_FPR23 = 0;
|
||
|
- vex_state->guest_FPR24 = 0;
|
||
|
- vex_state->guest_FPR25 = 0;
|
||
|
- vex_state->guest_FPR26 = 0;
|
||
|
- vex_state->guest_FPR27 = 0;
|
||
|
- vex_state->guest_FPR28 = 0;
|
||
|
- vex_state->guest_FPR29 = 0;
|
||
|
- vex_state->guest_FPR30 = 0;
|
||
|
- vex_state->guest_FPR31 = 0;
|
||
|
-
|
||
|
/* Initialise the vector state. */
|
||
|
# define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
|
||
|
|
||
|
- VECZERO(vex_state->guest_VR0 );
|
||
|
- VECZERO(vex_state->guest_VR1 );
|
||
|
- VECZERO(vex_state->guest_VR2 );
|
||
|
- VECZERO(vex_state->guest_VR3 );
|
||
|
- VECZERO(vex_state->guest_VR4 );
|
||
|
- VECZERO(vex_state->guest_VR5 );
|
||
|
- VECZERO(vex_state->guest_VR6 );
|
||
|
- VECZERO(vex_state->guest_VR7 );
|
||
|
- VECZERO(vex_state->guest_VR8 );
|
||
|
- VECZERO(vex_state->guest_VR9 );
|
||
|
- VECZERO(vex_state->guest_VR10);
|
||
|
- VECZERO(vex_state->guest_VR11);
|
||
|
- VECZERO(vex_state->guest_VR12);
|
||
|
- VECZERO(vex_state->guest_VR13);
|
||
|
- VECZERO(vex_state->guest_VR14);
|
||
|
- VECZERO(vex_state->guest_VR15);
|
||
|
- VECZERO(vex_state->guest_VR16);
|
||
|
- VECZERO(vex_state->guest_VR17);
|
||
|
- VECZERO(vex_state->guest_VR18);
|
||
|
- VECZERO(vex_state->guest_VR19);
|
||
|
- VECZERO(vex_state->guest_VR20);
|
||
|
- VECZERO(vex_state->guest_VR21);
|
||
|
- VECZERO(vex_state->guest_VR22);
|
||
|
- VECZERO(vex_state->guest_VR23);
|
||
|
- VECZERO(vex_state->guest_VR24);
|
||
|
- VECZERO(vex_state->guest_VR25);
|
||
|
- VECZERO(vex_state->guest_VR26);
|
||
|
- VECZERO(vex_state->guest_VR27);
|
||
|
- VECZERO(vex_state->guest_VR28);
|
||
|
- VECZERO(vex_state->guest_VR29);
|
||
|
- VECZERO(vex_state->guest_VR30);
|
||
|
- VECZERO(vex_state->guest_VR31);
|
||
|
+ VECZERO(vex_state->guest_VSR0 );
|
||
|
+ VECZERO(vex_state->guest_VSR1 );
|
||
|
+ VECZERO(vex_state->guest_VSR2 );
|
||
|
+ VECZERO(vex_state->guest_VSR3 );
|
||
|
+ VECZERO(vex_state->guest_VSR4 );
|
||
|
+ VECZERO(vex_state->guest_VSR5 );
|
||
|
+ VECZERO(vex_state->guest_VSR6 );
|
||
|
+ VECZERO(vex_state->guest_VSR7 );
|
||
|
+ VECZERO(vex_state->guest_VSR8 );
|
||
|
+ VECZERO(vex_state->guest_VSR9 );
|
||
|
+ VECZERO(vex_state->guest_VSR10);
|
||
|
+ VECZERO(vex_state->guest_VSR11);
|
||
|
+ VECZERO(vex_state->guest_VSR12);
|
||
|
+ VECZERO(vex_state->guest_VSR13);
|
||
|
+ VECZERO(vex_state->guest_VSR14);
|
||
|
+ VECZERO(vex_state->guest_VSR15);
|
||
|
+ VECZERO(vex_state->guest_VSR16);
|
||
|
+ VECZERO(vex_state->guest_VSR17);
|
||
|
+ VECZERO(vex_state->guest_VSR18);
|
||
|
+ VECZERO(vex_state->guest_VSR19);
|
||
|
+ VECZERO(vex_state->guest_VSR20);
|
||
|
+ VECZERO(vex_state->guest_VSR21);
|
||
|
+ VECZERO(vex_state->guest_VSR22);
|
||
|
+ VECZERO(vex_state->guest_VSR23);
|
||
|
+ VECZERO(vex_state->guest_VSR24);
|
||
|
+ VECZERO(vex_state->guest_VSR25);
|
||
|
+ VECZERO(vex_state->guest_VSR26);
|
||
|
+ VECZERO(vex_state->guest_VSR27);
|
||
|
+ VECZERO(vex_state->guest_VSR28);
|
||
|
+ VECZERO(vex_state->guest_VSR29);
|
||
|
+ VECZERO(vex_state->guest_VSR30);
|
||
|
+ VECZERO(vex_state->guest_VSR31);
|
||
|
+ VECZERO(vex_state->guest_VSR32);
|
||
|
+ VECZERO(vex_state->guest_VSR33);
|
||
|
+ VECZERO(vex_state->guest_VSR34);
|
||
|
+ VECZERO(vex_state->guest_VSR35);
|
||
|
+ VECZERO(vex_state->guest_VSR36);
|
||
|
+ VECZERO(vex_state->guest_VSR37);
|
||
|
+ VECZERO(vex_state->guest_VSR38);
|
||
|
+ VECZERO(vex_state->guest_VSR39);
|
||
|
+ VECZERO(vex_state->guest_VSR40);
|
||
|
+ VECZERO(vex_state->guest_VSR41);
|
||
|
+ VECZERO(vex_state->guest_VSR42);
|
||
|
+ VECZERO(vex_state->guest_VSR43);
|
||
|
+ VECZERO(vex_state->guest_VSR44);
|
||
|
+ VECZERO(vex_state->guest_VSR45);
|
||
|
+ VECZERO(vex_state->guest_VSR46);
|
||
|
+ VECZERO(vex_state->guest_VSR47);
|
||
|
+ VECZERO(vex_state->guest_VSR48);
|
||
|
+ VECZERO(vex_state->guest_VSR49);
|
||
|
+ VECZERO(vex_state->guest_VSR50);
|
||
|
+ VECZERO(vex_state->guest_VSR51);
|
||
|
+ VECZERO(vex_state->guest_VSR52);
|
||
|
+ VECZERO(vex_state->guest_VSR53);
|
||
|
+ VECZERO(vex_state->guest_VSR54);
|
||
|
+ VECZERO(vex_state->guest_VSR55);
|
||
|
+ VECZERO(vex_state->guest_VSR56);
|
||
|
+ VECZERO(vex_state->guest_VSR57);
|
||
|
+ VECZERO(vex_state->guest_VSR58);
|
||
|
+ VECZERO(vex_state->guest_VSR59);
|
||
|
+ VECZERO(vex_state->guest_VSR60);
|
||
|
+ VECZERO(vex_state->guest_VSR61);
|
||
|
+ VECZERO(vex_state->guest_VSR62);
|
||
|
+ VECZERO(vex_state->guest_VSR63);
|
||
|
|
||
|
# undef VECZERO
|
||
|
|
||
|
Index: VEX/priv/guest_ppc_toIR.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/guest_ppc_toIR.c.orig
|
||
|
+++ VEX/priv/guest_ppc_toIR.c
|
||
|
@@ -1,4 +1,5 @@
|
||
|
|
||
|
+
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
/*--- begin guest_ppc_toIR.c ---*/
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
@@ -257,22 +258,52 @@ static UChar ifieldRegDS( UInt instr ) {
|
||
|
return toUChar( IFIELD( instr, 21, 5 ) );
|
||
|
}
|
||
|
|
||
|
+/* Extract XT (destination register) field, instr[0,25:21] */
|
||
|
+static UChar ifieldRegXT ( UInt instr )
|
||
|
+{
|
||
|
+ UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
|
||
|
+ UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
|
||
|
+ return (upper_bit << 5) | lower_bits;
|
||
|
+}
|
||
|
+
|
||
|
+/* Extract XS (store source register) field, instr[0,25:21] */
|
||
|
+static inline UChar ifieldRegXS ( UInt instr )
|
||
|
+{
|
||
|
+ return ifieldRegXT ( instr );
|
||
|
+}
|
||
|
+
|
||
|
/* Extract RA (1st source register) field, instr[20:16] */
|
||
|
static UChar ifieldRegA ( UInt instr ) {
|
||
|
return toUChar( IFIELD( instr, 16, 5 ) );
|
||
|
}
|
||
|
|
||
|
+/* Extract XA (1st source register) field, instr[2,20:16] */
|
||
|
+static UChar ifieldRegXA ( UInt instr )
|
||
|
+{
|
||
|
+ UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
|
||
|
+ UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
|
||
|
+ return (upper_bit << 5) | lower_bits;
|
||
|
+}
|
||
|
+
|
||
|
/* Extract RB (2nd source register) field, instr[15:11] */
|
||
|
static UChar ifieldRegB ( UInt instr ) {
|
||
|
return toUChar( IFIELD( instr, 11, 5 ) );
|
||
|
}
|
||
|
|
||
|
+/* Extract XB (2nd source register) field, instr[1,15:11] */
|
||
|
+static UChar ifieldRegXB ( UInt instr )
|
||
|
+{
|
||
|
+ UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
|
||
|
+ UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
|
||
|
+ return (upper_bit << 5) | lower_bits;
|
||
|
+}
|
||
|
+
|
||
|
/* Extract RC (3rd source register) field, instr[10:6] */
|
||
|
static UChar ifieldRegC ( UInt instr ) {
|
||
|
return toUChar( IFIELD( instr, 6, 5 ) );
|
||
|
}
|
||
|
|
||
|
-/* Extract 2nd lowest bit, instr[1] */
|
||
|
+/* Extract bit 10, instr[10] */
|
||
|
static UChar ifieldBIT10 ( UInt instr ) {
|
||
|
return toUChar( IFIELD( instr, 10, 1 ) );
|
||
|
}
|
||
|
@@ -297,6 +328,16 @@ static UInt ifieldUIMM26 ( UInt instr )
|
||
|
return instr & 0x3FFFFFF;
|
||
|
}
|
||
|
|
||
|
+/* Extract DM field, instr[9:8] */
|
||
|
+static UChar ifieldDM ( UInt instr ) {
|
||
|
+ return toUChar( IFIELD( instr, 8, 2 ) );
|
||
|
+}
|
||
|
+
|
||
|
+/* Extract SHW field, instr[9:8] */
|
||
|
+static inline UChar ifieldSHW ( UInt instr )
|
||
|
+{
|
||
|
+ return ifieldDM ( instr );
|
||
|
+}
|
||
|
|
||
|
/*------------------------------------------------------------*/
|
||
|
/*--- Guest-state identifiers ---*/
|
||
|
@@ -506,6 +547,12 @@ static IRExpr* mkU64 ( ULong i )
|
||
|
return IRExpr_Const(IRConst_U64(i));
|
||
|
}
|
||
|
|
||
|
+static IRExpr* mkV128 ( UShort i )
|
||
|
+{
|
||
|
+ vassert(i == 0 || i == 0xffff);
|
||
|
+ return IRExpr_Const(IRConst_V128(i));
|
||
|
+}
|
||
|
+
|
||
|
/* This generates a normal (non load-linked) load. */
|
||
|
static IRExpr* loadBE ( IRType ty, IRExpr* addr )
|
||
|
{
|
||
|
@@ -932,43 +979,44 @@ static void putIReg ( UInt archreg, IREx
|
||
|
}
|
||
|
|
||
|
|
||
|
+/* Floating point egisters are mapped to VSX registers[0..31]. */
|
||
|
static Int floatGuestRegOffset ( UInt archreg )
|
||
|
{
|
||
|
vassert(archreg < 32);
|
||
|
|
||
|
switch (archreg) {
|
||
|
- case 0: return offsetofPPCGuestState(guest_FPR0);
|
||
|
- case 1: return offsetofPPCGuestState(guest_FPR1);
|
||
|
- case 2: return offsetofPPCGuestState(guest_FPR2);
|
||
|
- case 3: return offsetofPPCGuestState(guest_FPR3);
|
||
|
- case 4: return offsetofPPCGuestState(guest_FPR4);
|
||
|
- case 5: return offsetofPPCGuestState(guest_FPR5);
|
||
|
- case 6: return offsetofPPCGuestState(guest_FPR6);
|
||
|
- case 7: return offsetofPPCGuestState(guest_FPR7);
|
||
|
- case 8: return offsetofPPCGuestState(guest_FPR8);
|
||
|
- case 9: return offsetofPPCGuestState(guest_FPR9);
|
||
|
- case 10: return offsetofPPCGuestState(guest_FPR10);
|
||
|
- case 11: return offsetofPPCGuestState(guest_FPR11);
|
||
|
- case 12: return offsetofPPCGuestState(guest_FPR12);
|
||
|
- case 13: return offsetofPPCGuestState(guest_FPR13);
|
||
|
- case 14: return offsetofPPCGuestState(guest_FPR14);
|
||
|
- case 15: return offsetofPPCGuestState(guest_FPR15);
|
||
|
- case 16: return offsetofPPCGuestState(guest_FPR16);
|
||
|
- case 17: return offsetofPPCGuestState(guest_FPR17);
|
||
|
- case 18: return offsetofPPCGuestState(guest_FPR18);
|
||
|
- case 19: return offsetofPPCGuestState(guest_FPR19);
|
||
|
- case 20: return offsetofPPCGuestState(guest_FPR20);
|
||
|
- case 21: return offsetofPPCGuestState(guest_FPR21);
|
||
|
- case 22: return offsetofPPCGuestState(guest_FPR22);
|
||
|
- case 23: return offsetofPPCGuestState(guest_FPR23);
|
||
|
- case 24: return offsetofPPCGuestState(guest_FPR24);
|
||
|
- case 25: return offsetofPPCGuestState(guest_FPR25);
|
||
|
- case 26: return offsetofPPCGuestState(guest_FPR26);
|
||
|
- case 27: return offsetofPPCGuestState(guest_FPR27);
|
||
|
- case 28: return offsetofPPCGuestState(guest_FPR28);
|
||
|
- case 29: return offsetofPPCGuestState(guest_FPR29);
|
||
|
- case 30: return offsetofPPCGuestState(guest_FPR30);
|
||
|
- case 31: return offsetofPPCGuestState(guest_FPR31);
|
||
|
+ case 0: return offsetofPPCGuestState(guest_VSR0);
|
||
|
+ case 1: return offsetofPPCGuestState(guest_VSR1);
|
||
|
+ case 2: return offsetofPPCGuestState(guest_VSR2);
|
||
|
+ case 3: return offsetofPPCGuestState(guest_VSR3);
|
||
|
+ case 4: return offsetofPPCGuestState(guest_VSR4);
|
||
|
+ case 5: return offsetofPPCGuestState(guest_VSR5);
|
||
|
+ case 6: return offsetofPPCGuestState(guest_VSR6);
|
||
|
+ case 7: return offsetofPPCGuestState(guest_VSR7);
|
||
|
+ case 8: return offsetofPPCGuestState(guest_VSR8);
|
||
|
+ case 9: return offsetofPPCGuestState(guest_VSR9);
|
||
|
+ case 10: return offsetofPPCGuestState(guest_VSR10);
|
||
|
+ case 11: return offsetofPPCGuestState(guest_VSR11);
|
||
|
+ case 12: return offsetofPPCGuestState(guest_VSR12);
|
||
|
+ case 13: return offsetofPPCGuestState(guest_VSR13);
|
||
|
+ case 14: return offsetofPPCGuestState(guest_VSR14);
|
||
|
+ case 15: return offsetofPPCGuestState(guest_VSR15);
|
||
|
+ case 16: return offsetofPPCGuestState(guest_VSR16);
|
||
|
+ case 17: return offsetofPPCGuestState(guest_VSR17);
|
||
|
+ case 18: return offsetofPPCGuestState(guest_VSR18);
|
||
|
+ case 19: return offsetofPPCGuestState(guest_VSR19);
|
||
|
+ case 20: return offsetofPPCGuestState(guest_VSR20);
|
||
|
+ case 21: return offsetofPPCGuestState(guest_VSR21);
|
||
|
+ case 22: return offsetofPPCGuestState(guest_VSR22);
|
||
|
+ case 23: return offsetofPPCGuestState(guest_VSR23);
|
||
|
+ case 24: return offsetofPPCGuestState(guest_VSR24);
|
||
|
+ case 25: return offsetofPPCGuestState(guest_VSR25);
|
||
|
+ case 26: return offsetofPPCGuestState(guest_VSR26);
|
||
|
+ case 27: return offsetofPPCGuestState(guest_VSR27);
|
||
|
+ case 28: return offsetofPPCGuestState(guest_VSR28);
|
||
|
+ case 29: return offsetofPPCGuestState(guest_VSR29);
|
||
|
+ case 30: return offsetofPPCGuestState(guest_VSR30);
|
||
|
+ case 31: return offsetofPPCGuestState(guest_VSR31);
|
||
|
default: break;
|
||
|
}
|
||
|
vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
|
||
|
@@ -988,44 +1036,117 @@ static void putFReg ( UInt archreg, IREx
|
||
|
stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
|
||
|
}
|
||
|
|
||
|
+static Int vsxGuestRegOffset ( UInt archreg )
|
||
|
+{
|
||
|
+ vassert(archreg < 64);
|
||
|
+ switch (archreg) {
|
||
|
+ case 0: return offsetofPPCGuestState(guest_VSR0);
|
||
|
+ case 1: return offsetofPPCGuestState(guest_VSR1);
|
||
|
+ case 2: return offsetofPPCGuestState(guest_VSR2);
|
||
|
+ case 3: return offsetofPPCGuestState(guest_VSR3);
|
||
|
+ case 4: return offsetofPPCGuestState(guest_VSR4);
|
||
|
+ case 5: return offsetofPPCGuestState(guest_VSR5);
|
||
|
+ case 6: return offsetofPPCGuestState(guest_VSR6);
|
||
|
+ case 7: return offsetofPPCGuestState(guest_VSR7);
|
||
|
+ case 8: return offsetofPPCGuestState(guest_VSR8);
|
||
|
+ case 9: return offsetofPPCGuestState(guest_VSR9);
|
||
|
+ case 10: return offsetofPPCGuestState(guest_VSR10);
|
||
|
+ case 11: return offsetofPPCGuestState(guest_VSR11);
|
||
|
+ case 12: return offsetofPPCGuestState(guest_VSR12);
|
||
|
+ case 13: return offsetofPPCGuestState(guest_VSR13);
|
||
|
+ case 14: return offsetofPPCGuestState(guest_VSR14);
|
||
|
+ case 15: return offsetofPPCGuestState(guest_VSR15);
|
||
|
+ case 16: return offsetofPPCGuestState(guest_VSR16);
|
||
|
+ case 17: return offsetofPPCGuestState(guest_VSR17);
|
||
|
+ case 18: return offsetofPPCGuestState(guest_VSR18);
|
||
|
+ case 19: return offsetofPPCGuestState(guest_VSR19);
|
||
|
+ case 20: return offsetofPPCGuestState(guest_VSR20);
|
||
|
+ case 21: return offsetofPPCGuestState(guest_VSR21);
|
||
|
+ case 22: return offsetofPPCGuestState(guest_VSR22);
|
||
|
+ case 23: return offsetofPPCGuestState(guest_VSR23);
|
||
|
+ case 24: return offsetofPPCGuestState(guest_VSR24);
|
||
|
+ case 25: return offsetofPPCGuestState(guest_VSR25);
|
||
|
+ case 26: return offsetofPPCGuestState(guest_VSR26);
|
||
|
+ case 27: return offsetofPPCGuestState(guest_VSR27);
|
||
|
+ case 28: return offsetofPPCGuestState(guest_VSR28);
|
||
|
+ case 29: return offsetofPPCGuestState(guest_VSR29);
|
||
|
+ case 30: return offsetofPPCGuestState(guest_VSR30);
|
||
|
+ case 31: return offsetofPPCGuestState(guest_VSR31);
|
||
|
+ case 32: return offsetofPPCGuestState(guest_VSR32);
|
||
|
+ case 33: return offsetofPPCGuestState(guest_VSR33);
|
||
|
+ case 34: return offsetofPPCGuestState(guest_VSR34);
|
||
|
+ case 35: return offsetofPPCGuestState(guest_VSR35);
|
||
|
+ case 36: return offsetofPPCGuestState(guest_VSR36);
|
||
|
+ case 37: return offsetofPPCGuestState(guest_VSR37);
|
||
|
+ case 38: return offsetofPPCGuestState(guest_VSR38);
|
||
|
+ case 39: return offsetofPPCGuestState(guest_VSR39);
|
||
|
+ case 40: return offsetofPPCGuestState(guest_VSR40);
|
||
|
+ case 41: return offsetofPPCGuestState(guest_VSR41);
|
||
|
+ case 42: return offsetofPPCGuestState(guest_VSR42);
|
||
|
+ case 43: return offsetofPPCGuestState(guest_VSR43);
|
||
|
+ case 44: return offsetofPPCGuestState(guest_VSR44);
|
||
|
+ case 45: return offsetofPPCGuestState(guest_VSR45);
|
||
|
+ case 46: return offsetofPPCGuestState(guest_VSR46);
|
||
|
+ case 47: return offsetofPPCGuestState(guest_VSR47);
|
||
|
+ case 48: return offsetofPPCGuestState(guest_VSR48);
|
||
|
+ case 49: return offsetofPPCGuestState(guest_VSR49);
|
||
|
+ case 50: return offsetofPPCGuestState(guest_VSR50);
|
||
|
+ case 51: return offsetofPPCGuestState(guest_VSR51);
|
||
|
+ case 52: return offsetofPPCGuestState(guest_VSR52);
|
||
|
+ case 53: return offsetofPPCGuestState(guest_VSR53);
|
||
|
+ case 54: return offsetofPPCGuestState(guest_VSR54);
|
||
|
+ case 55: return offsetofPPCGuestState(guest_VSR55);
|
||
|
+ case 56: return offsetofPPCGuestState(guest_VSR56);
|
||
|
+ case 57: return offsetofPPCGuestState(guest_VSR57);
|
||
|
+ case 58: return offsetofPPCGuestState(guest_VSR58);
|
||
|
+ case 59: return offsetofPPCGuestState(guest_VSR59);
|
||
|
+ case 60: return offsetofPPCGuestState(guest_VSR60);
|
||
|
+ case 61: return offsetofPPCGuestState(guest_VSR61);
|
||
|
+ case 62: return offsetofPPCGuestState(guest_VSR62);
|
||
|
+ case 63: return offsetofPPCGuestState(guest_VSR63);
|
||
|
+ default: break;
|
||
|
+ }
|
||
|
+ vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
|
||
|
+}
|
||
|
|
||
|
+/* Vector registers are mapped to VSX registers[32..63]. */
|
||
|
static Int vectorGuestRegOffset ( UInt archreg )
|
||
|
{
|
||
|
vassert(archreg < 32);
|
||
|
|
||
|
switch (archreg) {
|
||
|
- case 0: return offsetofPPCGuestState(guest_VR0);
|
||
|
- case 1: return offsetofPPCGuestState(guest_VR1);
|
||
|
- case 2: return offsetofPPCGuestState(guest_VR2);
|
||
|
- case 3: return offsetofPPCGuestState(guest_VR3);
|
||
|
- case 4: return offsetofPPCGuestState(guest_VR4);
|
||
|
- case 5: return offsetofPPCGuestState(guest_VR5);
|
||
|
- case 6: return offsetofPPCGuestState(guest_VR6);
|
||
|
- case 7: return offsetofPPCGuestState(guest_VR7);
|
||
|
- case 8: return offsetofPPCGuestState(guest_VR8);
|
||
|
- case 9: return offsetofPPCGuestState(guest_VR9);
|
||
|
- case 10: return offsetofPPCGuestState(guest_VR10);
|
||
|
- case 11: return offsetofPPCGuestState(guest_VR11);
|
||
|
- case 12: return offsetofPPCGuestState(guest_VR12);
|
||
|
- case 13: return offsetofPPCGuestState(guest_VR13);
|
||
|
- case 14: return offsetofPPCGuestState(guest_VR14);
|
||
|
- case 15: return offsetofPPCGuestState(guest_VR15);
|
||
|
- case 16: return offsetofPPCGuestState(guest_VR16);
|
||
|
- case 17: return offsetofPPCGuestState(guest_VR17);
|
||
|
- case 18: return offsetofPPCGuestState(guest_VR18);
|
||
|
- case 19: return offsetofPPCGuestState(guest_VR19);
|
||
|
- case 20: return offsetofPPCGuestState(guest_VR20);
|
||
|
- case 21: return offsetofPPCGuestState(guest_VR21);
|
||
|
- case 22: return offsetofPPCGuestState(guest_VR22);
|
||
|
- case 23: return offsetofPPCGuestState(guest_VR23);
|
||
|
- case 24: return offsetofPPCGuestState(guest_VR24);
|
||
|
- case 25: return offsetofPPCGuestState(guest_VR25);
|
||
|
- case 26: return offsetofPPCGuestState(guest_VR26);
|
||
|
- case 27: return offsetofPPCGuestState(guest_VR27);
|
||
|
- case 28: return offsetofPPCGuestState(guest_VR28);
|
||
|
- case 29: return offsetofPPCGuestState(guest_VR29);
|
||
|
- case 30: return offsetofPPCGuestState(guest_VR30);
|
||
|
- case 31: return offsetofPPCGuestState(guest_VR31);
|
||
|
+ case 0: return offsetofPPCGuestState(guest_VSR32);
|
||
|
+ case 1: return offsetofPPCGuestState(guest_VSR33);
|
||
|
+ case 2: return offsetofPPCGuestState(guest_VSR34);
|
||
|
+ case 3: return offsetofPPCGuestState(guest_VSR35);
|
||
|
+ case 4: return offsetofPPCGuestState(guest_VSR36);
|
||
|
+ case 5: return offsetofPPCGuestState(guest_VSR37);
|
||
|
+ case 6: return offsetofPPCGuestState(guest_VSR38);
|
||
|
+ case 7: return offsetofPPCGuestState(guest_VSR39);
|
||
|
+ case 8: return offsetofPPCGuestState(guest_VSR40);
|
||
|
+ case 9: return offsetofPPCGuestState(guest_VSR41);
|
||
|
+ case 10: return offsetofPPCGuestState(guest_VSR42);
|
||
|
+ case 11: return offsetofPPCGuestState(guest_VSR43);
|
||
|
+ case 12: return offsetofPPCGuestState(guest_VSR44);
|
||
|
+ case 13: return offsetofPPCGuestState(guest_VSR45);
|
||
|
+ case 14: return offsetofPPCGuestState(guest_VSR46);
|
||
|
+ case 15: return offsetofPPCGuestState(guest_VSR47);
|
||
|
+ case 16: return offsetofPPCGuestState(guest_VSR48);
|
||
|
+ case 17: return offsetofPPCGuestState(guest_VSR49);
|
||
|
+ case 18: return offsetofPPCGuestState(guest_VSR50);
|
||
|
+ case 19: return offsetofPPCGuestState(guest_VSR51);
|
||
|
+ case 20: return offsetofPPCGuestState(guest_VSR52);
|
||
|
+ case 21: return offsetofPPCGuestState(guest_VSR53);
|
||
|
+ case 22: return offsetofPPCGuestState(guest_VSR54);
|
||
|
+ case 23: return offsetofPPCGuestState(guest_VSR55);
|
||
|
+ case 24: return offsetofPPCGuestState(guest_VSR56);
|
||
|
+ case 25: return offsetofPPCGuestState(guest_VSR57);
|
||
|
+ case 26: return offsetofPPCGuestState(guest_VSR58);
|
||
|
+ case 27: return offsetofPPCGuestState(guest_VSR59);
|
||
|
+ case 28: return offsetofPPCGuestState(guest_VSR60);
|
||
|
+ case 29: return offsetofPPCGuestState(guest_VSR61);
|
||
|
+ case 30: return offsetofPPCGuestState(guest_VSR62);
|
||
|
+ case 31: return offsetofPPCGuestState(guest_VSR63);
|
||
|
default: break;
|
||
|
}
|
||
|
vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
|
||
|
@@ -1045,6 +1166,22 @@ static void putVReg ( UInt archreg, IREx
|
||
|
stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
|
||
|
}
|
||
|
|
||
|
+/* Get contents of VSX guest register */
|
||
|
+static IRExpr* getVSReg ( UInt archreg )
|
||
|
+{
|
||
|
+ vassert(archreg < 64);
|
||
|
+ return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
|
||
|
+}
|
||
|
+
|
||
|
+/* Ditto, but write to a VSX reg instead. */
|
||
|
+static void putVSReg ( UInt archreg, IRExpr* e )
|
||
|
+{
|
||
|
+ vassert(archreg < 64);
|
||
|
+ vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
|
||
|
+ stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
static Int guestCR321offset ( UInt cr )
|
||
|
{
|
||
|
switch (cr) {
|
||
|
@@ -1075,6 +1212,42 @@ static Int guestCR0offset ( UInt cr )
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/* Generate an IR sequence to do a popcount operation on the supplied
|
||
|
+ * IRTemp, and return an IRTemp holding the result.
|
||
|
+ */
|
||
|
+static IRTemp gen_POPCOUNT ( IRTemp src )
|
||
|
+{
|
||
|
+ Int i, shift[6];
|
||
|
+ IRTemp old = IRTemp_INVALID;
|
||
|
+ IRTemp nyu = IRTemp_INVALID;
|
||
|
+ IRTemp mask[6];
|
||
|
+
|
||
|
+ vassert(typeOfIRExpr(irsb->tyenv,mkexpr(src)) == Ity_I64);
|
||
|
+ for (i = 0; i < 6; i++) {
|
||
|
+ mask[i] = newTemp( Ity_I64 );
|
||
|
+ shift[i] = 1 << i;
|
||
|
+ }
|
||
|
+ assign( mask[0], mkU64( 0x5555555555555555ULL ) );
|
||
|
+ assign( mask[1], mkU64( 0x3333333333333333ULL ) );
|
||
|
+ assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
|
||
|
+ assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
|
||
|
+ assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
|
||
|
+ assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
|
||
|
+ old = src;
|
||
|
+ for (i = 0; i < 6; i++) {
|
||
|
+ nyu = newTemp( Ity_I64 );
|
||
|
+ assign( nyu,
|
||
|
+ binop( Iop_Add64,
|
||
|
+ binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
|
||
|
+ binop( Iop_And64,
|
||
|
+ binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
|
||
|
+ mkexpr( mask[i] ) ) ) );
|
||
|
+ old = nyu;
|
||
|
+ }
|
||
|
+ return nyu;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
// ROTL(src32/64, rot_amt5/6)
|
||
|
static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
|
||
|
IRExpr* rot_amt )
|
||
|
@@ -2345,6 +2518,80 @@ static void putGST_field ( PPC_GST reg,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/*------------------------------------------------------------*/
|
||
|
+/* Helpers for VSX instructions that do floating point
|
||
|
+ * operations and need to determine if a src contains a
|
||
|
+ * special FP value.
|
||
|
+ *
|
||
|
+ *------------------------------------------------------------*/
|
||
|
+
|
||
|
+#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
|
||
|
+#define FP_FRAC_PART(x) binop( Iop_And64, \
|
||
|
+ mkexpr( x ), \
|
||
|
+ mkU64( NONZERO_FRAC_MASK ) )
|
||
|
+
|
||
|
+// Returns exponent part of floating point as I32
|
||
|
+static IRExpr * fp_exp_part(IRTemp src)
|
||
|
+{
|
||
|
+ IRExpr * exp;
|
||
|
+ if (!mode64)
|
||
|
+ exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
|
||
|
+ mkexpr( src ) ),
|
||
|
+ mkU8( 20 ) ), mkU32( 0x7ff ) );
|
||
|
+ else
|
||
|
+ exp = unop( Iop_64to32,
|
||
|
+ binop( Iop_And64,
|
||
|
+ binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
|
||
|
+ mkU64( 0x7ff ) ) );
|
||
|
+ return exp;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+// Infinity: exp = 7ff and fraction is zero; s = 0/1
|
||
|
+static IRExpr * is_Inf(IRTemp src)
|
||
|
+{
|
||
|
+ IRExpr * Inf_exp, * hi32, * low32;
|
||
|
+ IRTemp frac_part = newTemp(Ity_I64);
|
||
|
+
|
||
|
+ assign( frac_part, FP_FRAC_PART(src) );
|
||
|
+ Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ff ) );
|
||
|
+ hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
|
||
|
+ low32 = unop( Iop_64to32, mkexpr( frac_part ) );
|
||
|
+ return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
|
||
|
+ mkU32( 0 ) ) );
|
||
|
+}
|
||
|
+
|
||
|
+// Zero: exp is zero and fraction is zero; s = 0/1
|
||
|
+static IRExpr * is_Zero(IRTemp src)
|
||
|
+{
|
||
|
+#define SIGN_MASK 0x7fffffffffffffffULL
|
||
|
+ IRExpr * hi32, * low32;
|
||
|
+ IRTemp sign_less_part = newTemp(Ity_I64);
|
||
|
+
|
||
|
+ assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
|
||
|
+ hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
|
||
|
+ low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
|
||
|
+ return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
|
||
|
+ mkU32( 0 ) );
|
||
|
+}
|
||
|
+
|
||
|
+/* SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
|
||
|
+ * QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
|
||
|
+ * This function returns an IRExpr value of '1' for any type of NaN.
|
||
|
+ */
|
||
|
+static IRExpr * is_NaN(IRTemp src)
|
||
|
+{
|
||
|
+ IRExpr * NaN_exp, * hi32, * low32;
|
||
|
+ IRTemp frac_part = newTemp(Ity_I64);
|
||
|
+
|
||
|
+ assign( frac_part, FP_FRAC_PART(src) );
|
||
|
+ hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
|
||
|
+ low32 = unop( Iop_64to32, mkexpr( frac_part ) );
|
||
|
+ NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src ), mkU32( 0x7ffULL ) );
|
||
|
+
|
||
|
+ return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
|
||
|
+ mkU32( 0 ) ) );
|
||
|
+}
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------------*/
|
||
|
@@ -3264,6 +3511,13 @@ static Bool dis_int_logic ( UInt theInst
|
||
|
putFReg( rS_addr, mkexpr(frA));
|
||
|
return True;
|
||
|
}
|
||
|
+ case 0x1FA: // popcntd (population count doubleword
|
||
|
+ {
|
||
|
+ DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
|
||
|
+ IRTemp result = gen_POPCOUNT(rS);
|
||
|
+ putIReg( rA_addr, mkexpr(result) );
|
||
|
+ return True;
|
||
|
+ }
|
||
|
|
||
|
default:
|
||
|
vex_printf("dis_int_logic(ppc)(opc2)\n");
|
||
|
@@ -5485,7 +5739,23 @@ static Bool dis_int_ldst_rev ( UInt theI
|
||
|
putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
|
||
|
/* Signed */False) );
|
||
|
break;
|
||
|
-
|
||
|
+
|
||
|
+ case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
|
||
|
+ {
|
||
|
+ IRExpr * nextAddr;
|
||
|
+ IRTemp w3 = newTemp( Ity_I32 );
|
||
|
+ IRTemp w4 = newTemp( Ity_I32 );
|
||
|
+ DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
|
||
|
+ assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
|
||
|
+ assign( w2, gen_byterev32( w1 ) );
|
||
|
+ nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
|
||
|
+ assign( w3, loadBE( Ity_I32, nextAddr ) );
|
||
|
+ assign( w4, gen_byterev32( w3 ) );
|
||
|
+ putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
|
||
|
DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
|
||
|
assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
|
||
|
@@ -6059,6 +6329,17 @@ static Bool dis_fp_load ( UInt theInstr
|
||
|
binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
|
||
|
break;
|
||
|
|
||
|
+ case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
|
||
|
+ {
|
||
|
+ IRTemp dw = newTemp( Ity_I64 );
|
||
|
+ DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
|
||
|
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
|
||
|
+ assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
|
||
|
+ assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
|
||
|
+ putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
default:
|
||
|
vex_printf("dis_fp_load(ppc)(opc2)\n");
|
||
|
return False;
|
||
|
@@ -6591,7 +6872,238 @@ static Bool dis_fp_multadd ( UInt theIns
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * fe_flag is set to 1 if any of the following conditions occurs:
|
||
|
+ * - The double-precision floating-point operand in register FRA is a NaN or an
|
||
|
+ * Infinity.
|
||
|
+ * - The double-precision floating-point operand in register FRB is a Zero, a
|
||
|
+ * NaN, or an Infinity.
|
||
|
+ * - e_b is less than or equal to -1022.
|
||
|
+ * - e_b is greater than or equal to 1021.
|
||
|
+ * - The double-precision floating-point operand in register FRA is not a zero
|
||
|
+ * and the difference, e_a - e_b, is greater than or equal to 1023.
|
||
|
+ * - The double-precision floating-point operand in register FRA is not a zero
|
||
|
+ * and the difference, e_a - e_b, is less than or equal to -1021.
|
||
|
+ * - The double-precision floating-point operand in register FRA is not a zero
|
||
|
+ * and e_a is less than or equal to -970
|
||
|
+ * Otherwise fe_flag is set to 0.
|
||
|
+ *
|
||
|
+ * fg_flag is set to 1 if either of the following conditions occurs.
|
||
|
+ * - The double-precision floating-point operand in register FRA is an Infinity.
|
||
|
+ * - The double-precision floating-point operand in register FRB is a Zero, an
|
||
|
+ * Infinity, or a denormalized value.
|
||
|
+ * Otherwise fg_flag is set to 0.
|
||
|
+ *
|
||
|
+ */
|
||
|
+static Bool dis_fp_ftdiv ( UInt theInstr )
|
||
|
+{
|
||
|
+ UChar opc1 = ifieldOPC(theInstr);
|
||
|
+ UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
|
||
|
+ UChar b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
|
||
|
+ UChar frA_addr = ifieldRegA(theInstr);
|
||
|
+ UChar frB_addr = ifieldRegB(theInstr);
|
||
|
+ UChar b0 = ifieldBIT0(theInstr);
|
||
|
+
|
||
|
+ // The following temps are for holding intermediate results
|
||
|
+ IRTemp frA_I64 = newTemp(Ity_I64);
|
||
|
+ IRTemp frB_I64 = newTemp(Ity_I64);
|
||
|
+ IRTemp e_a = newTemp(Ity_I32);
|
||
|
+ IRTemp e_b = newTemp(Ity_I32);
|
||
|
+ IRTemp frA_exp_shR = newTemp(Ity_I32);
|
||
|
+ IRTemp frB_exp_shR = newTemp(Ity_I32);
|
||
|
+
|
||
|
+ UInt bias = 1023;
|
||
|
+
|
||
|
+ /* The following variables hold boolean results from tests
|
||
|
+ * that are OR'ed together for setting the fe_ and fg_ flags.
|
||
|
+ * For some cases, the booleans are used more than once, so
|
||
|
+ * I make those IRTemp's instead of IRExpr's.
|
||
|
+ */
|
||
|
+ IRExpr * fraNaN, * frbNaN, * frbDenorm;
|
||
|
+ IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
|
||
|
+ IRTemp fraInf_tmp = newTemp(Ity_I1);
|
||
|
+ IRTemp frbZero_tmp = newTemp(Ity_I1);
|
||
|
+ IRTemp frbInf_tmp = newTemp(Ity_I1);
|
||
|
+ IRTemp fraNotZero_tmp = newTemp(Ity_I1);
|
||
|
+
|
||
|
+/* The following are the flags that are set by OR'ing the results of
|
||
|
+ * all the tests done for ftdiv. These flags are the input to the specified CR.
|
||
|
+ */
|
||
|
+ IRExpr * fe_flag, * fl_flag, * fg_flag;
|
||
|
+
|
||
|
+
|
||
|
+ if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
|
||
|
+ vex_printf("dis_fp_ftdiv(ppc)(instr)\n");
|
||
|
+ return False;
|
||
|
+ }
|
||
|
|
||
|
+ // Create temps that will be used throughout the following tests.
|
||
|
+ assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
|
||
|
+ assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
|
||
|
+ assign( frA_exp_shR, fp_exp_part( frA_I64 ) );
|
||
|
+ assign( frB_exp_shR, fp_exp_part( frB_I64 ) );
|
||
|
+ /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
|
||
|
+ assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
|
||
|
+ assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
|
||
|
+
|
||
|
+
|
||
|
+ ////////////////// fe_flag tests BEGIN //////////////////////
|
||
|
+ /* We first do all tests that may result in setting fe_flag to '1'. */
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if the double-precision floating-point operand in register FRA is
|
||
|
+ * a NaN:
|
||
|
+ * exp = 7ff and fraction is non-zero; s = 0/1
|
||
|
+ */
|
||
|
+ fraNaN = is_NaN(frA_I64);
|
||
|
+ /*
|
||
|
+ * Test if the double-precision floating-point operand in register FRA is
|
||
|
+ * an Infinity.
|
||
|
+ * exp = 7ff and fraction is zero; s = 0/1
|
||
|
+ */
|
||
|
+ assign(fraInf_tmp, is_Inf(frA_I64));
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if the double-precision floating-point operand in register FRB is
|
||
|
+ * a NaN:
|
||
|
+ * exp = 7ff and fraction is non-zero; s = 0/1
|
||
|
+ */
|
||
|
+ frbNaN = is_NaN(frB_I64);
|
||
|
+ /*
|
||
|
+ * Test if the double-precision floating-point operand in register FRB is
|
||
|
+ * an Infinity.
|
||
|
+ * exp = 7ff and fraction is zero; s = 0/1
|
||
|
+ */
|
||
|
+ assign( frbInf_tmp, is_Inf(frB_I64) );
|
||
|
+ /*
|
||
|
+ * Test if the double-precision floating-point operand in register FRB is
|
||
|
+ * a Zero.
|
||
|
+ * exp is zero and fraction is zero; s = 0/1
|
||
|
+ */
|
||
|
+ assign( frbZero_tmp, is_Zero(frB_I64) );
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if e_b <= -1022
|
||
|
+ */
|
||
|
+ {
|
||
|
+ UInt test_value = 0xfffffc02; //Int test_value = -1022;
|
||
|
+ eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if e_b >= 1021
|
||
|
+ * ==> 1021 < e_b
|
||
|
+ */
|
||
|
+ {
|
||
|
+ Int test_value = 1021;
|
||
|
+ eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if FRA != Zero and (e_a - e_b) >= 1023
|
||
|
+ * ==> FRA != Zero && (1023 < (e_a - e_b)
|
||
|
+ */
|
||
|
+ assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_I64 ) ) );
|
||
|
+ ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
|
||
|
+ binop( Iop_CmpLT32S, mkU32( bias ),
|
||
|
+ binop( Iop_Sub32, mkexpr( e_a ),
|
||
|
+ mkexpr( e_b ) ) ) );
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if FRA != Zero and (e_a - e_b) <= -1021
|
||
|
+ */
|
||
|
+ {
|
||
|
+ UInt test_value = 0xfffffc03; //Int test_value = -1021;
|
||
|
+
|
||
|
+ ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
|
||
|
+ binop( Iop_CmpLE32S,
|
||
|
+ binop( Iop_Sub32,
|
||
|
+ mkexpr( e_a ),
|
||
|
+ mkexpr( e_b ) ),
|
||
|
+ mkU32( test_value ) ) );
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if FRA != Zero and e_a <= -970
|
||
|
+ */
|
||
|
+ {
|
||
|
+ UInt test_value = 0xfffffc36; //Int test_value = -970;
|
||
|
+
|
||
|
+ ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
|
||
|
+ mkexpr( e_a ),
|
||
|
+ mkU32( test_value ) ) );
|
||
|
+ }
|
||
|
+ ////////////////// fe_flag tests END //////////////////////
|
||
|
+
|
||
|
+ ////////////////// fg_flag tests BEGIN //////////////////////
|
||
|
+ /*
|
||
|
+ * The following tests were already performed above in the fe_flag
|
||
|
+ * tests. So these conditions will result in both fe_ and fg_ flags
|
||
|
+ * being set.
|
||
|
+ * - Test if FRA is an Infinity
|
||
|
+ * - Test if FRB ix Zero
|
||
|
+ * - Test if FRB is an Infinity
|
||
|
+ */
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Test if FRB holds a denormalized value. A denormalized value is one where
|
||
|
+ * the exp is 0 and the fraction is non-zero.
|
||
|
+ */
|
||
|
+ {
|
||
|
+ IRExpr * hi32, * low32, * fraction_is_nonzero;
|
||
|
+ IRTemp frac_part = newTemp(Ity_I64);
|
||
|
+
|
||
|
+ assign( frac_part, FP_FRAC_PART(frB_I64) );
|
||
|
+ hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
|
||
|
+ low32 = unop( Iop_64to32, mkexpr( frac_part ) );
|
||
|
+ fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
|
||
|
+ mkU32( 0 ) );
|
||
|
+ frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
|
||
|
+ mkU32( 0x0ULL ) ), fraction_is_nonzero );
|
||
|
+
|
||
|
+ }
|
||
|
+ ////////////////// fg_flag tests END //////////////////////
|
||
|
+
|
||
|
+ /////////////////////////
|
||
|
+ /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
|
||
|
+ * where fl_flag == 1 on ppc64.
|
||
|
+ */
|
||
|
+ fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
|
||
|
+
|
||
|
+
|
||
|
+ fe_flag
|
||
|
+ = mkOR1(
|
||
|
+ fraNaN,
|
||
|
+ mkOR1(
|
||
|
+ mkexpr( fraInf_tmp ),
|
||
|
+ mkOR1(
|
||
|
+ mkexpr( frbZero_tmp ),
|
||
|
+ mkOR1(
|
||
|
+ frbNaN,
|
||
|
+ mkOR1(
|
||
|
+ mkexpr( frbInf_tmp ),
|
||
|
+ mkOR1( eb_LTE,
|
||
|
+ mkOR1( eb_GTE,
|
||
|
+ mkOR1( ea_eb_GTE,
|
||
|
+ mkOR1( ea_eb_LTE,
|
||
|
+ ea_LTE ) ) ) ) ) ) ) ) );
|
||
|
+
|
||
|
+ fe_flag = unop(Iop_1Uto32, fe_flag);
|
||
|
+
|
||
|
+ fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
|
||
|
+ mkOR1( mkexpr( frbInf_tmp ),
|
||
|
+ frbDenorm ) ) );
|
||
|
+ fg_flag = unop(Iop_1Uto32, fg_flag);
|
||
|
+
|
||
|
+ putGST_field( PPC_GST_CR, binop( Iop_Or32,
|
||
|
+ binop( Iop_Or32,
|
||
|
+ binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
|
||
|
+ binop( Iop_Shl32, fg_flag, mkU8( 2 ) ) ),
|
||
|
+ binop( Iop_Shl32, fe_flag, mkU8( 1 ) ) ), crfD );
|
||
|
+
|
||
|
+ DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
|
||
|
+ return True;
|
||
|
+}
|
||
|
|
||
|
/*
|
||
|
Floating Point Compare Instructions
|
||
|
@@ -6721,13 +7233,34 @@ static Bool dis_fp_round ( UInt theInstr
|
||
|
simulating exceptions, the exception status will appear to be
|
||
|
zero. Hence cr1 should be cleared if this is a . form insn. */
|
||
|
Bool clear_CR1 = True;
|
||
|
-
|
||
|
- if (opc1 != 0x3F || b16to20 != 0) {
|
||
|
+ if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
|
||
|
vex_printf("dis_fp_round(ppc)(instr)\n");
|
||
|
return False;
|
||
|
}
|
||
|
|
||
|
assign( frB, getFReg(frB_addr));
|
||
|
+ // TODO : add support here for fcfdus
|
||
|
+ if (opc1 == 0x3B) {
|
||
|
+ /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
|
||
|
+ * they're very similar to the other instructions handled here, but have
|
||
|
+ * a different primary opcode.
|
||
|
+ */
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x34E: // fcfids (Float convert from signed DWord to single precision)
|
||
|
+ DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
|
||
|
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
|
||
|
+ assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
|
||
|
+ mkexpr( r_tmp64 ) ) ) );
|
||
|
+ goto putFR;
|
||
|
+
|
||
|
+ case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
|
||
|
+ DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
|
||
|
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
|
||
|
+ assign( frD, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) );
|
||
|
+ goto putFR;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
|
||
|
switch (opc2) {
|
||
|
case 0x00C: // frsp (Float Round to Single, PPC32 p423)
|
||
|
@@ -6780,6 +7313,12 @@ static Bool dis_fp_round ( UInt theInstr
|
||
|
binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
|
||
|
break;
|
||
|
|
||
|
+ case 0x3CE: // fcfidu (Float convert from unsigned DWord)
|
||
|
+ DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
|
||
|
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
|
||
|
+ assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
|
||
|
+ break;
|
||
|
+
|
||
|
case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
|
||
|
switch(opc2) {
|
||
|
case 0x188: // frin (Floating Round to Integer Nearest)
|
||
|
@@ -6830,7 +7369,7 @@ static Bool dis_fp_round ( UInt theInstr
|
||
|
vex_printf("dis_fp_round(ppc)(opc2)\n");
|
||
|
return False;
|
||
|
}
|
||
|
-
|
||
|
+putFR:
|
||
|
putFReg( frD_addr, mkexpr(frD) );
|
||
|
|
||
|
if (set_FPRF) {
|
||
|
@@ -7271,6 +7810,722 @@ static Bool dis_av_procctl ( UInt theIns
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
+ *
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_conv ( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX2-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT( theInstr );
|
||
|
+ UChar XB = ifieldRegXB( theInstr );
|
||
|
+ IRTemp frB = newTemp(Ity_F64);
|
||
|
+ IRTemp r_tmp64 = newTemp(Ity_I64);
|
||
|
+ IRExpr* rm = get_IR_roundingmode();
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_conv(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
|
||
|
+ /* For all the VSX convert instructions, the contents of doubleword element 1
|
||
|
+ * of VSX[XT] are undefined after the operation; therefore, we can simply
|
||
|
+ * move the entire array element where it makes sense to do so.
|
||
|
+ */
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x2B0:
|
||
|
+ // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
|
||
|
+ // to Signed Integer Doubleword format with Saturate)
|
||
|
+ DIP("xscvdpsxds fr%u,fr%u\n", (UInt)XT, (UInt)XB);
|
||
|
+ putVSReg( XT,
|
||
|
+ binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
|
||
|
+ mkU32( Irrm_ZERO ),
|
||
|
+ mkexpr( frB ) ), mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ case 0x2F0:
|
||
|
+ // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
|
||
|
+ // Double-Precision format)
|
||
|
+ DIP("xscvsxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
|
||
|
+
|
||
|
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
|
||
|
+ putVSReg( XT,
|
||
|
+ binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ binop( Iop_I64StoF64, rm,
|
||
|
+ mkexpr( r_tmp64 ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ case 0x2D0:
|
||
|
+ // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
|
||
|
+ // Double-Precision format)
|
||
|
+ DIP("xscvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
|
||
|
+
|
||
|
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
|
||
|
+ putVSReg( XT,
|
||
|
+ binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ binop( Iop_I64UtoF64, rm,
|
||
|
+ mkexpr( r_tmp64 ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Scalar Floating Point Arithmetic Instructions
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_arith ( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX3-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT( theInstr );
|
||
|
+ UChar XA = ifieldRegXA( theInstr );
|
||
|
+ UChar XB = ifieldRegXB( theInstr );
|
||
|
+ IRExpr* rm = get_IR_roundingmode();
|
||
|
+ IRTemp frA = newTemp(Ity_F64);
|
||
|
+ IRTemp frB = newTemp(Ity_F64);
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_arith(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
|
||
|
+ assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
|
||
|
+
|
||
|
+ /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
|
||
|
+ * of VSX[XT] are undefined after the operation; therefore, we can simply set
|
||
|
+ * element to zero where it makes sense to do so.
|
||
|
+ */
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x080: // xsadddp (VSX scalar add double-precision)
|
||
|
+ DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ triop( Iop_AddF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( frB ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
|
||
|
+ DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ triop( Iop_DivF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( frB ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
|
||
|
+ {
|
||
|
+ IRTemp frT = newTemp(Ity_F64);
|
||
|
+ Bool mdp = opc2 == 0x0A4;
|
||
|
+ DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
|
||
|
+ getVSReg( XT ) ) ) );
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ qop( Iop_MAddF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( mdp ? frT : frB ),
|
||
|
+ mkexpr( mdp ? frB : frT ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
|
||
|
+ {
|
||
|
+ IRTemp frT = newTemp(Ity_F64);
|
||
|
+ Bool mdp = opc2 == 0x0E4;
|
||
|
+ DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
|
||
|
+ getVSReg( XT ) ) ) );
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ qop( Iop_MSubF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( mdp ? frT : frB ),
|
||
|
+ mkexpr( mdp ? frB : frT ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
|
||
|
+ {
|
||
|
+ /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
|
||
|
+ * of fnmadd and use pretty much the same code. However, that code has a bug in the
|
||
|
+ * way it blindly negates the signbit, even if the floating point result is a NaN.
|
||
|
+ * So, the TODO is to fix fnmadd (which I'll do in a different patch).
|
||
|
+ */
|
||
|
+ ULong signbit_mask = 0x8000000000000000ULL;
|
||
|
+ Bool mdp = opc2 == 0x2A4;
|
||
|
+ IRTemp frT = newTemp(Ity_F64);
|
||
|
+ IRTemp maddResult = newTemp(Ity_I64);
|
||
|
+ IRTemp negatedResult = newTemp(Ity_I64);
|
||
|
+ IRTemp signbit_32 = newTemp(Ity_I32);
|
||
|
+ IRTemp resultantSignbit = newTemp(Ity_I1);
|
||
|
+
|
||
|
+ DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
|
||
|
+ getVSReg( XT ) ) ) );
|
||
|
+ assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( mdp ? frT : frB ),
|
||
|
+ mkexpr( mdp ? frB : frT ) ) ) );
|
||
|
+ assign( signbit_32, binop( Iop_Shr32,
|
||
|
+ unop( Iop_64HIto32,
|
||
|
+ binop( Iop_And64, mkexpr( maddResult ),
|
||
|
+ mkU64( signbit_mask ) ) ),
|
||
|
+ mkU8( 31 ) ) );
|
||
|
+ /* We negate the signbit if and only if the intermediate result from the
|
||
|
+ * multiply-add was NOT a NaN. This is an XNOR predicate.
|
||
|
+ */
|
||
|
+ assign( resultantSignbit,
|
||
|
+ unop( Iop_Not1,
|
||
|
+ binop( Iop_CmpEQ32,
|
||
|
+ binop( Iop_Xor32, mkexpr( signbit_32 ),
|
||
|
+ unop( Iop_1Uto32,
|
||
|
+ is_NaN( maddResult ) ) ),
|
||
|
+ mkU32( 1 ) ) ) );
|
||
|
+
|
||
|
+ assign( negatedResult,
|
||
|
+ binop( Iop_Or64, binop( Iop_And64, mkexpr( maddResult ),
|
||
|
+ mkU64( ~signbit_mask ) ),
|
||
|
+ binop( Iop_32HLto64,
|
||
|
+ binop( Iop_Shl32,
|
||
|
+ unop( Iop_1Uto32,
|
||
|
+ mkexpr( resultantSignbit ) ),
|
||
|
+ mkU8( 31 ) ), mkU32( 0 ) ) ) );
|
||
|
+
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( negatedResult ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
|
||
|
+ DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ triop( Iop_MulF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( frB ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+ case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
|
||
|
+ DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
|
||
|
+ triop( Iop_SubF64, rm,
|
||
|
+ mkexpr( frA ),
|
||
|
+ mkexpr( frB ) ) ),
|
||
|
+ mkU64( 0 ) ) );
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_arith(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Floating Point Compare Instructions
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_cmp( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX3-Form and XX2-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) );
|
||
|
+ IRTemp ccPPC32 = newTemp(Ity_I32);
|
||
|
+ IRTemp ccIR = newTemp(Ity_I32);
|
||
|
+ UChar XA = ifieldRegXA ( theInstr );
|
||
|
+ UChar XB = ifieldRegXB ( theInstr );
|
||
|
+ IRTemp frA = newTemp(Ity_F64);
|
||
|
+ IRTemp frB = newTemp(Ity_F64);
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
|
||
|
+ assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
|
||
|
+ /* Note: Differences between xscmpudp and xscmpodp are only in
|
||
|
+ * exception flag settings, which aren't supported anyway. */
|
||
|
+ DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
|
||
|
+ crfD, (UInt)XA, (UInt)XB);
|
||
|
+ assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
|
||
|
+
|
||
|
+ /* Map compare result from IR to PPC32 */
|
||
|
+ /*
|
||
|
+ FP cmp result | PPC | IR
|
||
|
+ --------------------------
|
||
|
+ UN | 0x1 | 0x45
|
||
|
+ EQ | 0x2 | 0x40
|
||
|
+ GT | 0x4 | 0x00
|
||
|
+ LT | 0x8 | 0x01
|
||
|
+ */
|
||
|
+
|
||
|
+ // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
|
||
|
+ // | ((ccIR ^ (ccIR>>6)) & 1)
|
||
|
+ assign(
|
||
|
+ ccPPC32,
|
||
|
+ binop(
|
||
|
+ Iop_Shl32,
|
||
|
+ mkU32(1),
|
||
|
+ unop(
|
||
|
+ Iop_32to8,
|
||
|
+ binop(
|
||
|
+ Iop_Or32,
|
||
|
+ binop(
|
||
|
+ Iop_And32,
|
||
|
+ unop(
|
||
|
+ Iop_Not32,
|
||
|
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
|
||
|
+ ),
|
||
|
+ mkU32(2)
|
||
|
+ ),
|
||
|
+ binop(
|
||
|
+ Iop_And32,
|
||
|
+ binop(
|
||
|
+ Iop_Xor32,
|
||
|
+ mkexpr(ccIR),
|
||
|
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
|
||
|
+ ),
|
||
|
+ mkU32(1)
|
||
|
+ )
|
||
|
+ )
|
||
|
+ )
|
||
|
+ )
|
||
|
+ );
|
||
|
+
|
||
|
+ putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
|
||
|
+
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+/*
|
||
|
+ * VSX Move Instructions
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_move( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX3-Form and XX2-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT ( theInstr );
|
||
|
+ UChar XA = ifieldRegXA ( theInstr );
|
||
|
+ UChar XB = ifieldRegXB ( theInstr );
|
||
|
+ IRTemp vA = newTemp( Ity_V128 );
|
||
|
+ IRTemp vB = newTemp( Ity_V128 );
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_move(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign( vA, getVSReg( XA ) );
|
||
|
+ assign( vB, getVSReg( XB ) );
|
||
|
+
|
||
|
+ /* For all the VSX move instructions, the contents of doubleword element 1
|
||
|
+ * of VSX[XT] are undefined after the operation; therefore, we can simply
|
||
|
+ * move the entire array element where it makes sense to do so.
|
||
|
+ */
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
|
||
|
+ {
|
||
|
+ /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
|
||
|
+ IRTemp absVal = newTemp(Ity_V128);
|
||
|
+ assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
|
||
|
+ DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
|
||
|
+ putVSReg(XT, mkexpr(absVal));
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x2C0: // xscpsgndp
|
||
|
+ {
|
||
|
+ /* Scalar copy sign double-precision */
|
||
|
+ IRTemp vecA_signbit = newTemp(Ity_V128);
|
||
|
+ IRTemp vecB_no_signbit = newTemp(Ity_V128);
|
||
|
+ IRTemp vec_result = newTemp(Ity_V128);
|
||
|
+ DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
|
||
|
+ mkexpr( vB ),
|
||
|
+ mkU8( 1 ) ),
|
||
|
+ mkU8( 1 ) ) );
|
||
|
+ assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
|
||
|
+ mkexpr( vA ),
|
||
|
+ mkU8( 127 ) ),
|
||
|
+ mkU8( 127 ) ) );
|
||
|
+ assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
|
||
|
+ putVSReg(XT, mkexpr(vec_result));
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x2D2: // xsnabsdp
|
||
|
+ {
|
||
|
+ /* Scalar negative absolute value double-precision */
|
||
|
+ IRTemp vec_neg_signbit = newTemp(Ity_V128);
|
||
|
+ DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
|
||
|
+ assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
|
||
|
+ mkV128( 0xffff ),
|
||
|
+ mkU8( 1 ) ) ) );
|
||
|
+ putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x2F2: // xsnegdp
|
||
|
+ {
|
||
|
+ /* Scalar negate double-precision */
|
||
|
+ IRTemp vecB_no_signbit = newTemp(Ity_V128);
|
||
|
+ IRTemp vecB_signbit_comp = newTemp(Ity_V128);
|
||
|
+ DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
|
||
|
+ assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
|
||
|
+ mkexpr( vB ),
|
||
|
+ mkU8( 1 ) ),
|
||
|
+ mkU8( 1 ) ) );
|
||
|
+ assign( vecB_signbit_comp, binop( Iop_ShlV128,
|
||
|
+ unop( Iop_NotV128,
|
||
|
+ binop( Iop_ShrV128,
|
||
|
+ mkexpr( vB ),
|
||
|
+ mkU8( 127 ) ) ),
|
||
|
+ mkU8( 127 ) ) );
|
||
|
+ putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
|
||
|
+ mkexpr( vecB_signbit_comp ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_move(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Logical Instructions
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_logic ( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX3-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT ( theInstr );
|
||
|
+ UChar XA = ifieldRegXA ( theInstr );
|
||
|
+ UChar XB = ifieldRegXB ( theInstr );
|
||
|
+ IRTemp vA = newTemp( Ity_V128 );
|
||
|
+ IRTemp vB = newTemp( Ity_V128 );
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_logic(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign( vA, getVSReg( XA ) );
|
||
|
+ assign( vB, getVSReg( XB ) );
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x268: // xxlxor
|
||
|
+ DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
|
||
|
+ break;
|
||
|
+ case 0x248: // xxlor
|
||
|
+ DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
|
||
|
+ break;
|
||
|
+ case 0x288: // xxlnor
|
||
|
+ DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
|
||
|
+ mkexpr( vB ) ) ) );
|
||
|
+ break;
|
||
|
+ case 0x208: // xxland
|
||
|
+ DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
|
||
|
+ break;
|
||
|
+ case 0x228: //xxlandc
|
||
|
+ DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
|
||
|
+ mkexpr( vB ) ) ) );
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Load Instructions
|
||
|
+ * NOTE: VSX supports word-aligned storage access.
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_load ( UInt theInstr )
|
||
|
+{
|
||
|
+ /* XX1-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT ( theInstr );
|
||
|
+ UChar rA_addr = ifieldRegA( theInstr );
|
||
|
+ UChar rB_addr = ifieldRegB( theInstr );
|
||
|
+ UInt opc2 = ifieldOPClo10( theInstr );
|
||
|
+
|
||
|
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
|
||
|
+ IRTemp EA = newTemp( ty );
|
||
|
+
|
||
|
+ if (opc1 != 0x1F) {
|
||
|
+ vex_printf( "dis_vx_load(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x24C: // lxsdx
|
||
|
+ {
|
||
|
+ IRExpr * exp;
|
||
|
+ DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
|
||
|
+ exp = loadBE( Ity_I64, mkexpr( EA ) );
|
||
|
+ // We need to pass an expression of type Ity_V128 with putVSReg, but the load
|
||
|
+ // we just performed is only a DW. But since the contents of VSR[XT] element 1
|
||
|
+ // are undefined after this operation, we can just do a splat op.
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x34C: // lxvd2x
|
||
|
+ {
|
||
|
+ IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
|
||
|
+ IRExpr * high, *low;
|
||
|
+ ULong ea_off = 8;
|
||
|
+ IRExpr* high_addr;
|
||
|
+ DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
|
||
|
+ high = loadBE( Ity_I64, mkexpr( EA ) );
|
||
|
+ high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
|
||
|
+ : mkU32( ea_off ) );
|
||
|
+ low = loadBE( Ity_I64, high_addr );
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x14C: // lxvdsx
|
||
|
+ {
|
||
|
+ IRTemp data = newTemp(Ity_I64);
|
||
|
+ DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
|
||
|
+ assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x30C:
|
||
|
+ {
|
||
|
+ IRExpr * t3, *t2, *t1, *t0;
|
||
|
+ UInt ea_off = 0;
|
||
|
+ IRExpr* irx_addr;
|
||
|
+
|
||
|
+ DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
|
||
|
+ t3 = loadBE( Ity_I32, mkexpr( EA ) );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ t2 = loadBE( Ity_I32, irx_addr );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ t1 = loadBE( Ity_I32, irx_addr );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ t0 = loadBE( Ity_I32, irx_addr );
|
||
|
+ putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
|
||
|
+ binop( Iop_32HLto64, t1, t0 ) ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_load(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Store Instructions
|
||
|
+ * NOTE: VSX supports word-aligned storage access.
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_store ( UInt theInstr )
|
||
|
+{
|
||
|
+ /* XX1-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XS = ifieldRegXS( theInstr );
|
||
|
+ UChar rA_addr = ifieldRegA( theInstr );
|
||
|
+ UChar rB_addr = ifieldRegB( theInstr );
|
||
|
+ IRTemp vS = newTemp( Ity_V128 );
|
||
|
+ UInt opc2 = ifieldOPClo10( theInstr );
|
||
|
+
|
||
|
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
|
||
|
+ IRTemp EA = newTemp( ty );
|
||
|
+
|
||
|
+ if (opc1 != 0x1F) {
|
||
|
+ vex_printf( "dis_vx_store(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
|
||
|
+ assign( vS, getVSReg( XS ) );
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x2CC:
|
||
|
+ {
|
||
|
+ IRExpr * high64;
|
||
|
+ DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
|
||
|
+ high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
|
||
|
+ storeBE( mkexpr( EA ), high64 );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x3CC:
|
||
|
+ {
|
||
|
+ IRExpr * high64, *low64;
|
||
|
+ DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
|
||
|
+ high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
|
||
|
+ low64 = unop( Iop_V128to64, mkexpr( vS ) );
|
||
|
+ storeBE( mkexpr( EA ), high64 );
|
||
|
+ storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
|
||
|
+ : mkU32( 8 ) ), low64 );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x38C:
|
||
|
+ {
|
||
|
+ UInt ea_off = 0;
|
||
|
+ IRExpr* irx_addr;
|
||
|
+ IRTemp hi64 = newTemp( Ity_I64 );
|
||
|
+ IRTemp lo64 = newTemp( Ity_I64 );
|
||
|
+
|
||
|
+ DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
|
||
|
+
|
||
|
+ // This instruction supports word-aligned stores, so EA may not be
|
||
|
+ // quad-word aligned. Therefore, do 4 individual word-size stores.
|
||
|
+ assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
|
||
|
+ assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
|
||
|
+
|
||
|
+ storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
|
||
|
+ ea_off += 4;
|
||
|
+ irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
|
||
|
+ ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
|
||
|
+ storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
|
||
|
+
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_store(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * VSX Permute Instructions
|
||
|
+ */
|
||
|
+static Bool
|
||
|
+dis_vx_permute( UInt theInstr, UInt opc2 )
|
||
|
+{
|
||
|
+ /* XX3-Form */
|
||
|
+ UChar opc1 = ifieldOPC( theInstr );
|
||
|
+ UChar XT = ifieldRegXT ( theInstr );
|
||
|
+ UChar XA = ifieldRegXA ( theInstr );
|
||
|
+ UChar XB = ifieldRegXB ( theInstr );
|
||
|
+ IRTemp vT = newTemp( Ity_V128 );
|
||
|
+ IRTemp vA = newTemp( Ity_V128 );
|
||
|
+ IRTemp vB = newTemp( Ity_V128 );
|
||
|
+
|
||
|
+ if (opc1 != 0x3C) {
|
||
|
+ vex_printf( "dis_vx_permute(ppc)(instr)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+
|
||
|
+ assign( vA, getVSReg( XA ) );
|
||
|
+ assign( vB, getVSReg( XB ) );
|
||
|
+
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
|
||
|
+ {
|
||
|
+ UChar SHW = ifieldSHW ( theInstr );
|
||
|
+ IRTemp result = newTemp(Ity_V128);
|
||
|
+ if ( SHW != 0 ) {
|
||
|
+ IRTemp hi = newTemp(Ity_V128);
|
||
|
+ IRTemp lo = newTemp(Ity_V128);
|
||
|
+ assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
|
||
|
+ assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
|
||
|
+ assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
|
||
|
+ } else
|
||
|
+ assign ( result, mkexpr(vA) );
|
||
|
+ DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
|
||
|
+ putVSReg( XT, mkexpr(result) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
|
||
|
+ {
|
||
|
+ UChar DM = ifieldDM ( theInstr );
|
||
|
+ IRTemp hi = newTemp(Ity_I64);
|
||
|
+ IRTemp lo = newTemp(Ity_I64);
|
||
|
+
|
||
|
+ if (DM & 0x2)
|
||
|
+ assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
|
||
|
+ else
|
||
|
+ assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
|
||
|
+
|
||
|
+ if (DM & 0x1)
|
||
|
+ assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
|
||
|
+ else
|
||
|
+ assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
|
||
|
+
|
||
|
+ assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
|
||
|
+
|
||
|
+ DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
|
||
|
+ putVSReg( XT, mkexpr( vT ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ case 0x48: // xxmrghw (VSX Merge High Word)
|
||
|
+ case 0xc8: // xxmrglw (VSX Merge Low Word)
|
||
|
+ {
|
||
|
+ char type = (opc2 == 0x48) ? 'h' : 'l';
|
||
|
+ IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
|
||
|
+ IRTemp a64 = newTemp(Ity_I64);
|
||
|
+ IRTemp ahi32 = newTemp(Ity_I32);
|
||
|
+ IRTemp alo32 = newTemp(Ity_I32);
|
||
|
+ IRTemp b64 = newTemp(Ity_I64);
|
||
|
+ IRTemp bhi32 = newTemp(Ity_I32);
|
||
|
+ IRTemp blo32 = newTemp(Ity_I32);
|
||
|
+
|
||
|
+ assign( a64, unop(word_op, mkexpr(vA)) );
|
||
|
+ assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
|
||
|
+ assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
|
||
|
+
|
||
|
+ assign( b64, unop(word_op, mkexpr(vB)) );
|
||
|
+ assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
|
||
|
+ assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
|
||
|
+
|
||
|
+ assign( vT, binop(Iop_64HLtoV128,
|
||
|
+ binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
|
||
|
+ binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
|
||
|
+
|
||
|
+ DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
|
||
|
+ putVSReg( XT, mkexpr( vT ) );
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ default:
|
||
|
+ vex_printf( "dis_vx_permute(ppc)(opc2)\n" );
|
||
|
+ return False;
|
||
|
+ }
|
||
|
+ return True;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
AltiVec Load Instructions
|
||
|
*/
|
||
|
static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
|
||
|
@@ -7400,7 +8655,6 @@ static Bool dis_av_load ( VexAbiInfo* vb
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
-
|
||
|
/*
|
||
|
AltiVec Store Instructions
|
||
|
*/
|
||
|
@@ -9238,8 +10492,221 @@ static Bool dis_av_fp_convert ( UInt the
|
||
|
}
|
||
|
|
||
|
|
||
|
+/* The 0x3C primary opcode (VSX category) uses several different forms of
|
||
|
+ * extended opcodes:
|
||
|
+ * o XX2-form:
|
||
|
+ * - [10:2] (IBM notation [21:29])
|
||
|
+ * o XX3-form variants:
|
||
|
+ * - variant 1: [10:3] (IBM notation [21:28])
|
||
|
+ * - variant 2: [9:3] (IBM notation [22:28])
|
||
|
+ * - variant 3: [7:3] (IBM notation [24:28])
|
||
|
+ * o XX-4 form:
|
||
|
+ * - [10:6] (IBM notation [21:25])
|
||
|
+ *
|
||
|
+ * The XX2-form needs bit 0 masked from the standard extended opcode
|
||
|
+ * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
|
||
|
+ * and the XX4-form needs bits 0, 1, and 2 masked. Additionally, the
|
||
|
+ * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
|
||
|
+ * front end since their encoding does not begin at bit 21 like the standard
|
||
|
+ * format.
|
||
|
+ *
|
||
|
+ * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
|
||
|
+ * secondary opcode for such VSX instructions.
|
||
|
+ *
|
||
|
+*/
|
||
|
+
|
||
|
+
|
||
|
+struct vsx_insn {
|
||
|
+ UInt opcode;
|
||
|
+ Char * name;
|
||
|
+};
|
||
|
+
|
||
|
+// ATTENTION: Keep this array sorted on the opcocde!!!
|
||
|
+static struct vsx_insn vsx_all[] = {
|
||
|
+ { 0x8, "xxsldwi" },
|
||
|
+ { 0x18, "xxsel" },
|
||
|
+ { 0x28, "xxpermdi" },
|
||
|
+ { 0x48, "xxmrghw" },
|
||
|
+ { 0x80, "xsadddp" },
|
||
|
+ { 0x84, "xsmaddadp" },
|
||
|
+ { 0x8c, "xscmpudp" },
|
||
|
+ { 0x90, "xscvdpuxws" },
|
||
|
+ { 0x92, "xsrdpi" },
|
||
|
+ { 0x94, "xsrsqrtedp" },
|
||
|
+ { 0x96, "xssqrtdp" },
|
||
|
+ { 0xa0, "xssubdp" },
|
||
|
+ { 0xa4, "xsmaddmdp" },
|
||
|
+ { 0xac, "xscmpodp" },
|
||
|
+ { 0xb0, "xscvdpsxws" },
|
||
|
+ { 0xb2, "xsrdpiz" },
|
||
|
+ { 0xb4, "xsredp" },
|
||
|
+ { 0xc0, "xsmuldp" },
|
||
|
+ { 0xc4, "xsmsubadp" },
|
||
|
+ { 0xc8, "xxmrglw" },
|
||
|
+ { 0xd2, "xsrdpip" },
|
||
|
+ { 0xd4, "xstsqrtdp" },
|
||
|
+ { 0xd6, "xsrdpic" },
|
||
|
+ { 0xe0, "xsdivdp" },
|
||
|
+ { 0xe4, "xsmsubmdp" },
|
||
|
+ { 0xf2, "xsrdpim" },
|
||
|
+ { 0xf4, "xstdivdp" },
|
||
|
+ { 0x100, "xvaddsp" },
|
||
|
+ { 0x104, "xvmaddasp" },
|
||
|
+ { 0x10c, "xvcmpeqsp" },
|
||
|
+ { 0x110, "xvcvspuxws" },
|
||
|
+ { 0x112, "xvrspi" },
|
||
|
+ { 0x114, "xvrsqrtesp" },
|
||
|
+ { 0x116, "xvsqrtsp" },
|
||
|
+ { 0x120, "xvsubsp" },
|
||
|
+ { 0x124, "xvmaddmsp" },
|
||
|
+ { 0x12c, "xvcmpgtsp" },
|
||
|
+ { 0x130, "xvcvspsxws" },
|
||
|
+ { 0x132, "xvrspiz" },
|
||
|
+ { 0x134, "xvresp" },
|
||
|
+ { 0x140, "xvmulsp" },
|
||
|
+ { 0x144, "xvmsubasp" },
|
||
|
+ { 0x148, "xxspltw" },
|
||
|
+ { 0x14c, "xvcmpgesp" },
|
||
|
+ { 0x150, "xvcvuxwsp" },
|
||
|
+ { 0x152, "xvrspip" },
|
||
|
+ { 0x154, "xvtsqrtsp" },
|
||
|
+ { 0x156, "xvrspic" },
|
||
|
+ { 0x160, "xvdivsp" },
|
||
|
+ { 0x164, "xvmsubmsp" },
|
||
|
+ { 0x170, "xvcvsxwsp" },
|
||
|
+ { 0x172, "xvrspim" },
|
||
|
+ { 0x174, "xvtdivsp" },
|
||
|
+ { 0x180, "xvadddp" },
|
||
|
+ { 0x184, "xvmaddadp" },
|
||
|
+ { 0x18c, "xvcmpeqdp" },
|
||
|
+ { 0x190, "xvcvdpuxws" },
|
||
|
+ { 0x192, "xvrdpi" },
|
||
|
+ { 0x194, "xvrsqrtedp" },
|
||
|
+ { 0x196, "xvsqrtdp" },
|
||
|
+ { 0x1a0, "xvsubdp" },
|
||
|
+ { 0x1a4, "xvmaddmdp" },
|
||
|
+ { 0x1ac, "xvcmpgtdp" },
|
||
|
+ { 0x1b0, "xvcvdpsxws" },
|
||
|
+ { 0x1b2, "xvrdpiz" },
|
||
|
+ { 0x1b4, "xvredp" },
|
||
|
+ { 0x1c0, "xvmuldp" },
|
||
|
+ { 0x1c4, "xvmsubadp" },
|
||
|
+ { 0x1cc, "xvcmpgedp" },
|
||
|
+ { 0x1d0, "xvcvuxwdp" },
|
||
|
+ { 0x1d2, "xvrdpip" },
|
||
|
+ { 0x1d4, "xvtsqrtdp" },
|
||
|
+ { 0x1d6, "xvrdpic" },
|
||
|
+ { 0x1e0, "xvdivdp" },
|
||
|
+ { 0x1e4, "xvmsubmdp" },
|
||
|
+ { 0x1f0, "xvcvsxwdp" },
|
||
|
+ { 0x1f2, "xvrdpim" },
|
||
|
+ { 0x1f4, "xvtdivdp" },
|
||
|
+ { 0x208, "xxland" },
|
||
|
+ { 0x212, "xscvdpsp" },
|
||
|
+ { 0x228, "xxlandc" },
|
||
|
+ { 0x248 , "xxlor" },
|
||
|
+ { 0x268, "xxlxor" },
|
||
|
+ { 0x280, "xsmaxdp" },
|
||
|
+ { 0x284, "xsnmaddadp" },
|
||
|
+ { 0x288, "xxlnor" },
|
||
|
+ { 0x290, "xscvdpuxds" },
|
||
|
+ { 0x292, "xscvspdp" },
|
||
|
+ { 0x2a0, "xsmindp" },
|
||
|
+ { 0x2a4, "xsnmaddmdp" },
|
||
|
+ { 0x2b0, "xscvdpsxds" },
|
||
|
+ { 0x2b2, "xsabsdp" },
|
||
|
+ { 0x2c0, "xscpsgndp" },
|
||
|
+ { 0x2c4, "xsnmsubadp" },
|
||
|
+ { 0x2d0, "xscvuxddp" },
|
||
|
+ { 0x2d2, "xsnabsdp" },
|
||
|
+ { 0x2e4, "xsnmsubmdp" },
|
||
|
+ { 0x2f0, "xscvsxddp" },
|
||
|
+ { 0x2f2, "xsnegdp" },
|
||
|
+ { 0x300, "xvmaxsp" },
|
||
|
+ { 0x304, "xvnmaddasp" },
|
||
|
+ { 0x30c, "xvcmpeqsp." },
|
||
|
+ { 0x310, "xvcvspuxds" },
|
||
|
+ { 0x312, "xvcvdpsp" },
|
||
|
+ { 0x320, "xvminsp" },
|
||
|
+ { 0x324, "xvnmaddmsp" },
|
||
|
+ { 0x32c, "xvcmpgtsp." },
|
||
|
+ { 0x330, "xvcvspsxds" },
|
||
|
+ { 0x332, "xvabssp" },
|
||
|
+ { 0x340, "xvcpsgnsp" },
|
||
|
+ { 0x344, "xvnmsubasp" },
|
||
|
+ { 0x34c, "xvcmpgesp." },
|
||
|
+ { 0x350, "xvcvuxdsp" },
|
||
|
+ { 0x352, "xvnabssp" },
|
||
|
+ { 0x364, "xvnmsubmsp" },
|
||
|
+ { 0x370, "xvcvsxdsp" },
|
||
|
+ { 0x372, "xvnegsp" },
|
||
|
+ { 0x380, "xvmaxdp" },
|
||
|
+ { 0x384, "xvnmaddadp" },
|
||
|
+ { 0x38c, "xvcmpeqdp." },
|
||
|
+ { 0x390, "xvcvdpuxds" },
|
||
|
+ { 0x392, "xvcvspdp" },
|
||
|
+ { 0x3a0, "xvmindp" },
|
||
|
+ { 0x3a4, "xvnmaddmdp" },
|
||
|
+ { 0x3ac, "xvcmpgtdp." },
|
||
|
+ { 0x3b0, "xvcvdpsxds" },
|
||
|
+ { 0x3b2, "xvabsdp" },
|
||
|
+ { 0x3c0, "xvcpsgndp" },
|
||
|
+ { 0x3c4, "xvnmsubadp" },
|
||
|
+ { 0x3cc, "xvcmpgedp." },
|
||
|
+ { 0x3d0, "xvcvuxddp" },
|
||
|
+ { 0x3d2, "xvnabsdp" },
|
||
|
+ { 0x3e4, "xvnmsubmdp" },
|
||
|
+ { 0x3f0, "xvcvsxddp" },
|
||
|
+ { 0x3f2, "xvnegdp" }
|
||
|
+};
|
||
|
+#define VSX_ALL_LEN 135
|
||
|
+
|
||
|
+// ATTENTION: This search function assumes vsx_all array is sorted.
|
||
|
+static Int findVSXextOpCode(UInt opcode)
|
||
|
+{
|
||
|
+ Int low, mid, high;
|
||
|
+ low = 0;
|
||
|
+ high = VSX_ALL_LEN - 1;
|
||
|
+ while (low <= high) {
|
||
|
+ mid = (low + high)/2;
|
||
|
+ if (opcode < vsx_all[mid].opcode)
|
||
|
+ high = mid - 1;
|
||
|
+ else if (opcode > vsx_all[mid].opcode)
|
||
|
+ low = mid + 1;
|
||
|
+ else
|
||
|
+ return mid;
|
||
|
+ }
|
||
|
+ return -1;
|
||
|
+}
|
||
|
|
||
|
|
||
|
+/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
|
||
|
+ * passed, and we then try to match it up with one of the above
|
||
|
+ * VSX forms.
|
||
|
+ */
|
||
|
+static UInt get_VSX60_opc2(UInt opc2_full)
|
||
|
+{
|
||
|
+#define XX2_MASK 0x000003FE
|
||
|
+#define XX3_1_MASK 0x000003FC
|
||
|
+#define XX3_2_MASK 0x000001FC
|
||
|
+#define XX3_3_MASK 0x0000007C
|
||
|
+#define XX4_MASK 0x000003E0
|
||
|
+ Int ret;
|
||
|
+ UInt vsxExtOpcode = 0;
|
||
|
+
|
||
|
+ if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
|
||
|
+ vsxExtOpcode = vsx_all[ret].opcode;
|
||
|
+ else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
|
||
|
+ vsxExtOpcode = vsx_all[ret].opcode;
|
||
|
+ else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
|
||
|
+ vsxExtOpcode = vsx_all[ret].opcode;
|
||
|
+ else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
|
||
|
+ vsxExtOpcode = vsx_all[ret].opcode;
|
||
|
+ else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
|
||
|
+ vsxExtOpcode = vsx_all[ret].opcode;
|
||
|
+
|
||
|
+ return vsxExtOpcode;
|
||
|
+}
|
||
|
|
||
|
/*------------------------------------------------------------*/
|
||
|
/*--- Disassemble a single instruction ---*/
|
||
|
@@ -9268,6 +10735,7 @@ DisResult disInstr_PPC_WRK (
|
||
|
Bool allow_V = False;
|
||
|
Bool allow_FX = False;
|
||
|
Bool allow_GX = False;
|
||
|
+ Bool allow_VX = False;
|
||
|
UInt hwcaps = archinfo->hwcaps;
|
||
|
Long delta;
|
||
|
|
||
|
@@ -9277,11 +10745,13 @@ DisResult disInstr_PPC_WRK (
|
||
|
allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
|
||
|
allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
|
||
|
allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
|
||
|
+ allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
|
||
|
} else {
|
||
|
allow_F = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
|
||
|
allow_V = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
|
||
|
allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
|
||
|
allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
|
||
|
+ allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
|
||
|
}
|
||
|
|
||
|
/* The running delta */
|
||
|
@@ -9473,6 +10943,20 @@ DisResult disInstr_PPC_WRK (
|
||
|
|
||
|
case 0x3B:
|
||
|
if (!allow_F) goto decode_noF;
|
||
|
+ opc2 = ifieldOPClo10(theInstr);
|
||
|
+ switch (opc2) {
|
||
|
+ case 0x3CE: // fcfidus (implemented as native insn
|
||
|
+ if (!allow_VX)
|
||
|
+ goto decode_noVX;
|
||
|
+ if (dis_fp_round( theInstr ))
|
||
|
+ goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x34E: // fcfids
|
||
|
+ if (dis_fp_round( theInstr ))
|
||
|
+ goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ }
|
||
|
+
|
||
|
opc2 = IFIELD(theInstr, 1, 5);
|
||
|
switch (opc2) {
|
||
|
/* Floating Point Arith Instructions */
|
||
|
@@ -9499,12 +10983,64 @@ DisResult disInstr_PPC_WRK (
|
||
|
if (!allow_GX) goto decode_noGX;
|
||
|
if (dis_fp_arith(theInstr)) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
-
|
||
|
+
|
||
|
default:
|
||
|
goto decode_failure;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
+ case 0x3C: // VSX instructions (except load/store)
|
||
|
+ {
|
||
|
+ UInt vsxOpc2 = get_VSX60_opc2(opc2);
|
||
|
+ /* The vsxOpc2 returned is the "normalized" value, representing the
|
||
|
+ * instructions secondary opcode as taken from the standard secondary
|
||
|
+ * opcode field [21:30] (IBM notatition), even if the actual field
|
||
|
+ * is non-standard. These normalized values are given in the opcode
|
||
|
+ * appendices of the ISA 2.06 document.
|
||
|
+ */
|
||
|
+ if (vsxOpc2 == 0)
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
+ switch (vsxOpc2) {
|
||
|
+ case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
|
||
|
+ if (dis_vx_permute(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
|
||
|
+ if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x2B2: // xsabsdp
|
||
|
+ if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x2C0: // xscpsgndp
|
||
|
+ if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x2D2: // xsnabsdp
|
||
|
+ if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x2F2: // xsnegdp
|
||
|
+ if (dis_vx_move(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
|
||
|
+ if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x080: case 0x0E0: // xsadddp, xsdivdp
|
||
|
+ case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
|
||
|
+ case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
|
||
|
+ case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
|
||
|
+ case 0x0C0: // xsmuldp
|
||
|
+ case 0x0A0: // xssubdp
|
||
|
+ if (dis_vx_arith(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+ case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
|
||
|
+ if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
+ default:
|
||
|
+ goto decode_failure;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
/* 64bit Integer Stores */
|
||
|
case 0x3E: // std, stdu
|
||
|
if (!mode64) goto decode_failure;
|
||
|
@@ -9555,6 +11091,10 @@ DisResult disInstr_PPC_WRK (
|
||
|
if (dis_fp_cmp(theInstr)) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
|
||
|
+ case 0x080: // ftdiv
|
||
|
+ if (dis_fp_ftdiv(theInstr)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
/* Floating Point Rounding/Conversion Instructions */
|
||
|
case 0x00C: // frsp
|
||
|
case 0x00E: // fctiw
|
||
|
@@ -9564,6 +11104,11 @@ DisResult disInstr_PPC_WRK (
|
||
|
case 0x34E: // fcfid
|
||
|
if (dis_fp_round(theInstr)) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
+ case 0x3CE: // fcfidu (implemented as native insn)
|
||
|
+ if (!allow_VX) goto decode_noVX;
|
||
|
+ if (dis_fp_round(theInstr)) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
|
||
|
/* Power6 rounding stuff */
|
||
|
case 0x1E8: // frim
|
||
|
@@ -9730,7 +11275,7 @@ DisResult disInstr_PPC_WRK (
|
||
|
|
||
|
/* Integer Load and Store with Byte Reverse Instructions */
|
||
|
case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
|
||
|
- case 0x296: // stwbrx
|
||
|
+ case 0x296: case 0x214: // stwbrx, ldbrx
|
||
|
if (dis_int_ldst_rev( theInstr )) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
|
||
|
@@ -9815,6 +11360,11 @@ DisResult disInstr_PPC_WRK (
|
||
|
if (dis_fp_load( theInstr )) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
|
||
|
+ case 0x377: // lfiwzx
|
||
|
+ if (!allow_F) goto decode_noF;
|
||
|
+ if (dis_fp_load( theInstr )) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
/* AltiVec instructions */
|
||
|
|
||
|
/* AV Cache Control - Data streams */
|
||
|
@@ -9838,6 +11388,26 @@ DisResult disInstr_PPC_WRK (
|
||
|
if (dis_av_store( theInstr )) goto decode_success;
|
||
|
goto decode_failure;
|
||
|
|
||
|
+ /* VSX Load */
|
||
|
+ case 0x24C: // lxsdx
|
||
|
+ case 0x34C: // lxvd2x
|
||
|
+ case 0x14C: // lxvdsx
|
||
|
+ case 0x30C: // lxvw4x
|
||
|
+ if (dis_vx_load( theInstr )) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
+ /* VSX Store */
|
||
|
+ case 0x2CC: // stxsdx
|
||
|
+ case 0x3CC: // stxvd2x
|
||
|
+ case 0x38C: // stxvw4x
|
||
|
+ if (dis_vx_store( theInstr )) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
+ /* Miscellaneous ISA 2.06 instructions */
|
||
|
+ case 0x1FA: // popcntd
|
||
|
+ if (dis_int_logic( theInstr )) goto decode_success;
|
||
|
+ goto decode_failure;
|
||
|
+
|
||
|
default:
|
||
|
/* Deal with some other cases that we would otherwise have
|
||
|
punted on. */
|
||
|
@@ -10023,6 +11593,10 @@ DisResult disInstr_PPC_WRK (
|
||
|
vassert(!allow_V);
|
||
|
vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
|
||
|
goto decode_failure;
|
||
|
+ decode_noVX:
|
||
|
+ vassert(!allow_VX);
|
||
|
+ vex_printf("disInstr(ppc): declined to decode a VSX insn.\n");
|
||
|
+ goto decode_failure;
|
||
|
decode_noFX:
|
||
|
vassert(!allow_FX);
|
||
|
vex_printf("disInstr(ppc): "
|
||
|
@@ -10105,10 +11679,10 @@ DisResult disInstr_PPC ( IRSB* ir
|
||
|
|
||
|
/* do some sanity checks */
|
||
|
mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
|
||
|
- | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX;
|
||
|
+ | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
|
||
|
|
||
|
- mask64 = VEX_HWCAPS_PPC64_V
|
||
|
- | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX;
|
||
|
+ mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
|
||
|
+ | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
|
||
|
|
||
|
if (mode64) {
|
||
|
vassert((hwcaps_guest & mask32) == 0);
|
||
|
Index: VEX/priv/host_ppc_defs.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/host_ppc_defs.c.orig
|
||
|
+++ VEX/priv/host_ppc_defs.c
|
||
|
@@ -962,12 +962,14 @@ PPCInstr* PPCInstr_FpRSP ( HReg dst, HRe
|
||
|
i->Pin.FpRSP.src = src;
|
||
|
return i;
|
||
|
}
|
||
|
-PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32,
|
||
|
- HReg dst, HReg src ) {
|
||
|
+PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
|
||
|
+ Bool dst64, HReg dst, HReg src ) {
|
||
|
PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
|
||
|
i->tag = Pin_FpCftI;
|
||
|
i->Pin.FpCftI.fromI = fromI;
|
||
|
i->Pin.FpCftI.int32 = int32;
|
||
|
+ i->Pin.FpCftI.syned = syned;
|
||
|
+ i->Pin.FpCftI.dst64 = dst64;
|
||
|
i->Pin.FpCftI.dst = dst;
|
||
|
i->Pin.FpCftI.src = src;
|
||
|
vassert(!(int32 && fromI)); /* no such insn ("fcfiw"). */
|
||
|
@@ -1433,15 +1435,21 @@ void ppPPCInstr ( PPCInstr* i, Bool mode
|
||
|
ppHRegPPC(i->Pin.FpRSP.src);
|
||
|
return;
|
||
|
case Pin_FpCftI: {
|
||
|
- HChar* str = "fc???";
|
||
|
+ HChar* str = "fc?????";
|
||
|
if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
|
||
|
str = "fctid";
|
||
|
else
|
||
|
if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
|
||
|
str = "fctiw";
|
||
|
else
|
||
|
- if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
|
||
|
- str = "fcfid";
|
||
|
+ if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
|
||
|
+ if (i->Pin.FpCftI.syned == True)
|
||
|
+ str = "fcfid";
|
||
|
+ else if (i->Pin.FpCftI.dst64 == True)
|
||
|
+ str = "fcfidu";
|
||
|
+ else
|
||
|
+ str = "fcfidus";
|
||
|
+ }
|
||
|
vex_printf("%s ", str);
|
||
|
ppHRegPPC(i->Pin.FpCftI.dst);
|
||
|
vex_printf(",");
|
||
|
@@ -3385,9 +3393,19 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf
|
||
|
goto done;
|
||
|
}
|
||
|
if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
|
||
|
- // fcfid (conv i64 to f64), PPC64 p434
|
||
|
- p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
|
||
|
- goto done;
|
||
|
+ if (i->Pin.FpCftI.syned == True) {
|
||
|
+ // fcfid (conv i64 to f64), PPC64 p434
|
||
|
+ p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
|
||
|
+ goto done;
|
||
|
+ } else if (i->Pin.FpCftI.dst64 == True) {
|
||
|
+ // fcfidu (conv u64 to f64)
|
||
|
+ p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
|
||
|
+ goto done;
|
||
|
+ } else {
|
||
|
+ // fcfidus (conv u64 to f32)
|
||
|
+ p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0);
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
}
|
||
|
goto bad;
|
||
|
}
|
||
|
Index: VEX/priv/host_ppc_defs.h
|
||
|
===================================================================
|
||
|
--- VEX/priv/host_ppc_defs.h.orig
|
||
|
+++ VEX/priv/host_ppc_defs.h
|
||
|
@@ -667,6 +667,8 @@ typedef
|
||
|
struct {
|
||
|
Bool fromI; /* False==F->I, True==I->F */
|
||
|
Bool int32; /* True== I is 32, False==I is 64 */
|
||
|
+ Bool syned;
|
||
|
+ Bool dst64; /* True==dest is 64bit; False==dest is 32bit */
|
||
|
HReg src;
|
||
|
HReg dst;
|
||
|
} FpCftI;
|
||
|
@@ -811,8 +813,8 @@ extern PPCInstr* PPCInstr_FpMulAcc ( P
|
||
|
extern PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz, HReg, PPCAMode* );
|
||
|
extern PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data );
|
||
|
extern PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src );
|
||
|
-extern PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32,
|
||
|
- HReg dst, HReg src );
|
||
|
+extern PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
|
||
|
+ Bool dst64, HReg dst, HReg src );
|
||
|
extern PPCInstr* PPCInstr_FpCMov ( PPCCondCode, HReg dst, HReg src );
|
||
|
extern PPCInstr* PPCInstr_FpLdFPSCR ( HReg src );
|
||
|
extern PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR );
|
||
|
Index: VEX/priv/host_ppc_isel.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/host_ppc_isel.c.orig
|
||
|
+++ VEX/priv/host_ppc_isel.c
|
||
|
@@ -126,7 +126,10 @@ fnabs[.] if .
|
||
|
|
||
|
fadd[.] if . y y
|
||
|
fadds[.] if . y y
|
||
|
-fcfid[.] (i64->dbl) if . y y
|
||
|
+fcfid[.] (Si64->dbl) if . y y
|
||
|
+fcfidU[.] (Ui64->dbl) if . y y
|
||
|
+fcfids[.] (Si64->sngl) if . Y Y
|
||
|
+fcfidus[.] (Ui64->sngl) if . Y Y
|
||
|
fcmpo (cmp, result n n n
|
||
|
fcmpu to crfD) n n n
|
||
|
fctid[.] (dbl->i64) if . ->undef y
|
||
|
@@ -559,7 +562,7 @@ PPCAMode* genGuestArrayOffset ( ISelEnv*
|
||
|
|
||
|
if (bias < -100 || bias > 100) /* somewhat arbitrarily */
|
||
|
vpanic("genGuestArrayOffset(ppc host)(3)");
|
||
|
- if (descr->base < 0 || descr->base > 4000) /* somewhat arbitrarily */
|
||
|
+ if (descr->base < 0 || descr->base > 5000) /* somewhat arbitrarily */
|
||
|
vpanic("genGuestArrayOffset(ppc host)(4)");
|
||
|
|
||
|
/* Compute off into a reg, %off. Then return:
|
||
|
@@ -1468,8 +1471,8 @@ static HReg iselWordExpr_R_wrk ( ISelEnv
|
||
|
set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
|
||
|
|
||
|
sub_from_sp( env, 16 );
|
||
|
- addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
|
||
|
- ftmp, fsrc));
|
||
|
+ addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/, True,
|
||
|
+ False, ftmp, fsrc));
|
||
|
addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
|
||
|
addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
|
||
|
|
||
|
@@ -1496,8 +1499,8 @@ static HReg iselWordExpr_R_wrk ( ISelEnv
|
||
|
set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
|
||
|
|
||
|
sub_from_sp( env, 16 );
|
||
|
- addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
|
||
|
- ftmp, fsrc));
|
||
|
+ addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/, True,
|
||
|
+ True, ftmp, fsrc));
|
||
|
addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
|
||
|
addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
|
||
|
add_to_sp( env, 16 );
|
||
|
@@ -2400,8 +2403,10 @@ static PPCCondCode iselCondCode_wrk ( IS
|
||
|
switch (e->Iex.Binop.op) {
|
||
|
case Iop_CmpEQ32: return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
|
||
|
case Iop_CmpNE32: return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
|
||
|
- case Iop_CmpLT32U: return mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
|
||
|
- case Iop_CmpLE32U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
|
||
|
+ case Iop_CmpLT32U: case Iop_CmpLT32S:
|
||
|
+ return mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
|
||
|
+ case Iop_CmpLE32U: case Iop_CmpLE32S:
|
||
|
+ return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
|
||
|
default: vpanic("iselCondCode(ppc): CmpXX32");
|
||
|
}
|
||
|
}
|
||
|
@@ -2746,8 +2751,8 @@ static void iselInt64Expr_wrk ( HReg* rH
|
||
|
set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
|
||
|
|
||
|
sub_from_sp( env, 16 );
|
||
|
- addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
|
||
|
- ftmp, fsrc));
|
||
|
+ addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/, True,
|
||
|
+ True, ftmp, fsrc));
|
||
|
addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
|
||
|
addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
|
||
|
addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
|
||
|
@@ -3185,7 +3190,8 @@ static HReg iselDblExpr_wrk ( ISelEnv* e
|
||
|
return r_dst;
|
||
|
}
|
||
|
|
||
|
- if (e->Iex.Binop.op == Iop_I64StoF64) {
|
||
|
+ if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64
|
||
|
+ || e->Iex.Binop.op == Iop_I64UtoF32) {
|
||
|
if (mode64) {
|
||
|
HReg fdst = newVRegF(env);
|
||
|
HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
|
||
|
@@ -3200,6 +3206,8 @@ static HReg iselDblExpr_wrk ( ISelEnv* e
|
||
|
addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
|
||
|
addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
|
||
|
addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
|
||
|
+ e->Iex.Binop.op == Iop_I64StoF64 ? True : False,
|
||
|
+ e->Iex.Binop.op == Iop_I64UtoF32 ? False : True,
|
||
|
fdst, fdst));
|
||
|
|
||
|
add_to_sp( env, 16 );
|
||
|
@@ -3226,6 +3234,8 @@ static HReg iselDblExpr_wrk ( ISelEnv* e
|
||
|
addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
|
||
|
addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
|
||
|
addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
|
||
|
+ e->Iex.Binop.op == Iop_I64StoF64 ? True : False,
|
||
|
+ e->Iex.Binop.op == Iop_I64UtoF32 ? False : True,
|
||
|
fdst, fdst));
|
||
|
|
||
|
add_to_sp( env, 16 );
|
||
|
@@ -4129,10 +4139,10 @@ HInstrArray* iselSB_PPC ( IRSB* bb, VexA
|
||
|
|
||
|
/* do some sanity checks */
|
||
|
mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
|
||
|
- | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX;
|
||
|
+ | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
|
||
|
|
||
|
- mask64 = VEX_HWCAPS_PPC64_V
|
||
|
- | VEX_HWCAPS_PPC64_FX | VEX_HWCAPS_PPC64_GX;
|
||
|
+ mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
|
||
|
+ | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
|
||
|
|
||
|
if (mode64) {
|
||
|
vassert((hwcaps_host & mask32) == 0);
|
||
|
Index: VEX/priv/ir_defs.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/ir_defs.c.orig
|
||
|
+++ VEX/priv/ir_defs.c
|
||
|
@@ -362,6 +362,8 @@ void ppIROp ( IROp op )
|
||
|
case Iop_I16StoF64: vex_printf("I16StoF64"); return;
|
||
|
case Iop_I32StoF64: vex_printf("I32StoF64"); return;
|
||
|
case Iop_I64StoF64: vex_printf("I64StoF64"); return;
|
||
|
+ case Iop_I64UtoF64: vex_printf("I64UtoF64"); return;
|
||
|
+ case Iop_I64UtoF32: vex_printf("I64UtoF32"); return;
|
||
|
|
||
|
case Iop_I32UtoF64: vex_printf("I32UtoF64"); return;
|
||
|
|
||
|
@@ -2262,6 +2264,8 @@ void typeOfPrimop ( IROp op,
|
||
|
case Iop_I16StoF64: UNARY(Ity_I16, Ity_F64);
|
||
|
case Iop_I32StoF64: UNARY(Ity_I32, Ity_F64);
|
||
|
case Iop_I64StoF64: BINARY(ity_RMode,Ity_I64, Ity_F64);
|
||
|
+ case Iop_I64UtoF64: BINARY(ity_RMode,Ity_I64, Ity_F64);
|
||
|
+ case Iop_I64UtoF32: BINARY(ity_RMode,Ity_I64, Ity_F64);
|
||
|
|
||
|
case Iop_I32UtoF64: UNARY(Ity_I32, Ity_F64);
|
||
|
|
||
|
Index: VEX/priv/main_main.c
|
||
|
===================================================================
|
||
|
--- VEX/priv/main_main.c.orig
|
||
|
+++ VEX/priv/main_main.c
|
||
|
@@ -855,6 +855,7 @@ static HChar* show_hwcaps_ppc32 ( UInt h
|
||
|
const UInt V = VEX_HWCAPS_PPC32_V;
|
||
|
const UInt FX = VEX_HWCAPS_PPC32_FX;
|
||
|
const UInt GX = VEX_HWCAPS_PPC32_GX;
|
||
|
+ const UInt VX = VEX_HWCAPS_PPC32_VX;
|
||
|
UInt c = hwcaps;
|
||
|
if (c == 0) return "ppc32-int";
|
||
|
if (c == F) return "ppc32-int-flt";
|
||
|
@@ -865,6 +866,7 @@ static HChar* show_hwcaps_ppc32 ( UInt h
|
||
|
if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
|
||
|
if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
|
||
|
if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
|
||
|
+ if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -875,6 +877,7 @@ static HChar* show_hwcaps_ppc64 ( UInt h
|
||
|
const UInt V = VEX_HWCAPS_PPC64_V;
|
||
|
const UInt FX = VEX_HWCAPS_PPC64_FX;
|
||
|
const UInt GX = VEX_HWCAPS_PPC64_GX;
|
||
|
+ const UInt VX = VEX_HWCAPS_PPC64_VX;
|
||
|
UInt c = hwcaps;
|
||
|
if (c == 0) return "ppc64-int-flt";
|
||
|
if (c == FX) return "ppc64-int-flt-FX";
|
||
|
@@ -884,6 +887,7 @@ static HChar* show_hwcaps_ppc64 ( UInt h
|
||
|
if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
|
||
|
if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
|
||
|
if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
|
||
|
+ if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Index: VEX/pub/libvex_guest_ppc32.h
|
||
|
===================================================================
|
||
|
--- VEX/pub/libvex_guest_ppc32.h.orig
|
||
|
+++ VEX/pub/libvex_guest_ppc32.h
|
||
|
@@ -82,120 +82,128 @@ typedef
|
||
|
/* 120 */ UInt guest_GPR30;
|
||
|
/* 124 */ UInt guest_GPR31;
|
||
|
|
||
|
- // Floating Point Registers
|
||
|
- /* 128 */ ULong guest_FPR0;
|
||
|
- /* 136 */ ULong guest_FPR1;
|
||
|
- /* 144 */ ULong guest_FPR2;
|
||
|
- /* 152 */ ULong guest_FPR3;
|
||
|
- /* 160 */ ULong guest_FPR4;
|
||
|
- /* 168 */ ULong guest_FPR5;
|
||
|
- /* 176 */ ULong guest_FPR6;
|
||
|
- /* 184 */ ULong guest_FPR7;
|
||
|
- /* 192 */ ULong guest_FPR8;
|
||
|
- /* 200 */ ULong guest_FPR9;
|
||
|
- /* 208 */ ULong guest_FPR10;
|
||
|
- /* 216 */ ULong guest_FPR11;
|
||
|
- /* 224 */ ULong guest_FPR12;
|
||
|
- /* 232 */ ULong guest_FPR13;
|
||
|
- /* 240 */ ULong guest_FPR14;
|
||
|
- /* 248 */ ULong guest_FPR15;
|
||
|
- /* 256 */ ULong guest_FPR16;
|
||
|
- /* 264 */ ULong guest_FPR17;
|
||
|
- /* 272 */ ULong guest_FPR18;
|
||
|
- /* 280 */ ULong guest_FPR19;
|
||
|
- /* 288 */ ULong guest_FPR20;
|
||
|
- /* 296 */ ULong guest_FPR21;
|
||
|
- /* 304 */ ULong guest_FPR22;
|
||
|
- /* 312 */ ULong guest_FPR23;
|
||
|
- /* 320 */ ULong guest_FPR24;
|
||
|
- /* 328 */ ULong guest_FPR25;
|
||
|
- /* 336 */ ULong guest_FPR26;
|
||
|
- /* 344 */ ULong guest_FPR27;
|
||
|
- /* 352 */ ULong guest_FPR28;
|
||
|
- /* 360 */ ULong guest_FPR29;
|
||
|
- /* 368 */ ULong guest_FPR30;
|
||
|
- /* 376 */ ULong guest_FPR31;
|
||
|
+ // Vector Registers, Floating Point Registers, and VSX Registers
|
||
|
+ // With ISA 2.06, the "Vector-Scalar Floating-point" category
|
||
|
+ // provides facilities to support vector and scalar binary floating-
|
||
|
+ // point operations. A unified register file is an integral part
|
||
|
+ // of this new facility, combining floating point and vector registers
|
||
|
+ // using a 64x128-bit vector. These are referred to as VSR[0..63].
|
||
|
+ // The floating point registers are now mapped into double word element 0
|
||
|
+ // of VSR[0..31]. The 32x128-bit vector registers defined by the "Vector
|
||
|
+ // Facility [Category: Vector]" are now mapped to VSR[32..63].
|
||
|
|
||
|
- // Vector Registers
|
||
|
// IMPORTANT: the user of libvex must place the guest state so as
|
||
|
- // to ensure that guest_VR{0..31}, and any shadows thereof, are
|
||
|
+ // to ensure that guest_VSR{0..63}, and any shadows thereof, are
|
||
|
// 16-aligned.
|
||
|
- /* 384 */ U128 guest_VR0;
|
||
|
- /* 400 */ U128 guest_VR1;
|
||
|
- /* 416 */ U128 guest_VR2;
|
||
|
- /* 432 */ U128 guest_VR3;
|
||
|
- /* 448 */ U128 guest_VR4;
|
||
|
- /* 464 */ U128 guest_VR5;
|
||
|
- /* 480 */ U128 guest_VR6;
|
||
|
- /* 496 */ U128 guest_VR7;
|
||
|
- /* 512 */ U128 guest_VR8;
|
||
|
- /* 528 */ U128 guest_VR9;
|
||
|
- /* 544 */ U128 guest_VR10;
|
||
|
- /* 560 */ U128 guest_VR11;
|
||
|
- /* 576 */ U128 guest_VR12;
|
||
|
- /* 592 */ U128 guest_VR13;
|
||
|
- /* 608 */ U128 guest_VR14;
|
||
|
- /* 624 */ U128 guest_VR15;
|
||
|
- /* 640 */ U128 guest_VR16;
|
||
|
- /* 656 */ U128 guest_VR17;
|
||
|
- /* 672 */ U128 guest_VR18;
|
||
|
- /* 688 */ U128 guest_VR19;
|
||
|
- /* 704 */ U128 guest_VR20;
|
||
|
- /* 720 */ U128 guest_VR21;
|
||
|
- /* 736 */ U128 guest_VR22;
|
||
|
- /* 752 */ U128 guest_VR23;
|
||
|
- /* 768 */ U128 guest_VR24;
|
||
|
- /* 784 */ U128 guest_VR25;
|
||
|
- /* 800 */ U128 guest_VR26;
|
||
|
- /* 816 */ U128 guest_VR27;
|
||
|
- /* 832 */ U128 guest_VR28;
|
||
|
- /* 848 */ U128 guest_VR29;
|
||
|
- /* 864 */ U128 guest_VR30;
|
||
|
- /* 880 */ U128 guest_VR31;
|
||
|
-
|
||
|
- /* 896 */ UInt guest_CIA; // IP (no arch visible register)
|
||
|
- /* 900 */ UInt guest_LR; // Link Register
|
||
|
- /* 904 */ UInt guest_CTR; // Count Register
|
||
|
+
|
||
|
+ /* 128 */ U128 guest_VSR0;
|
||
|
+ /* 144 */ U128 guest_VSR1;
|
||
|
+ /* 160 */ U128 guest_VSR2;
|
||
|
+ /* 176 */ U128 guest_VSR3;
|
||
|
+ /* 192 */ U128 guest_VSR4;
|
||
|
+ /* 208 */ U128 guest_VSR5;
|
||
|
+ /* 224 */ U128 guest_VSR6;
|
||
|
+ /* 240 */ U128 guest_VSR7;
|
||
|
+ /* 256 */ U128 guest_VSR8;
|
||
|
+ /* 272 */ U128 guest_VSR9;
|
||
|
+ /* 288 */ U128 guest_VSR10;
|
||
|
+ /* 304 */ U128 guest_VSR11;
|
||
|
+ /* 320 */ U128 guest_VSR12;
|
||
|
+ /* 336 */ U128 guest_VSR13;
|
||
|
+ /* 352 */ U128 guest_VSR14;
|
||
|
+ /* 368 */ U128 guest_VSR15;
|
||
|
+ /* 384 */ U128 guest_VSR16;
|
||
|
+ /* 400 */ U128 guest_VSR17;
|
||
|
+ /* 416 */ U128 guest_VSR18;
|
||
|
+ /* 432 */ U128 guest_VSR19;
|
||
|
+ /* 448 */ U128 guest_VSR20;
|
||
|
+ /* 464 */ U128 guest_VSR21;
|
||
|
+ /* 480 */ U128 guest_VSR22;
|
||
|
+ /* 496 */ U128 guest_VSR23;
|
||
|
+ /* 512 */ U128 guest_VSR24;
|
||
|
+ /* 528 */ U128 guest_VSR25;
|
||
|
+ /* 544 */ U128 guest_VSR26;
|
||
|
+ /* 560 */ U128 guest_VSR27;
|
||
|
+ /* 576 */ U128 guest_VSR28;
|
||
|
+ /* 592 */ U128 guest_VSR29;
|
||
|
+ /* 608 */ U128 guest_VSR30;
|
||
|
+ /* 624 */ U128 guest_VSR31;
|
||
|
+ /* 640 */ U128 guest_VSR32;
|
||
|
+ /* 656 */ U128 guest_VSR33;
|
||
|
+ /* 672 */ U128 guest_VSR34;
|
||
|
+ /* 688 */ U128 guest_VSR35;
|
||
|
+ /* 704 */ U128 guest_VSR36;
|
||
|
+ /* 720 */ U128 guest_VSR37;
|
||
|
+ /* 736 */ U128 guest_VSR38;
|
||
|
+ /* 752 */ U128 guest_VSR39;
|
||
|
+ /* 768 */ U128 guest_VSR40;
|
||
|
+ /* 784 */ U128 guest_VSR41;
|
||
|
+ /* 800 */ U128 guest_VSR42;
|
||
|
+ /* 816 */ U128 guest_VSR43;
|
||
|
+ /* 832 */ U128 guest_VSR44;
|
||
|
+ /* 848 */ U128 guest_VSR45;
|
||
|
+ /* 864 */ U128 guest_VSR46;
|
||
|
+ /* 880 */ U128 guest_VSR47;
|
||
|
+ /* 896 */ U128 guest_VSR48;
|
||
|
+ /* 912 */ U128 guest_VSR49;
|
||
|
+ /* 928 */ U128 guest_VSR50;
|
||
|
+ /* 944 */ U128 guest_VSR51;
|
||
|
+ /* 960 */ U128 guest_VSR52;
|
||
|
+ /* 976 */ U128 guest_VSR53;
|
||
|
+ /* 992 */ U128 guest_VSR54;
|
||
|
+ /* 1008 */ U128 guest_VSR55;
|
||
|
+ /* 1024 */ U128 guest_VSR56;
|
||
|
+ /* 1040 */ U128 guest_VSR57;
|
||
|
+ /* 1056 */ U128 guest_VSR58;
|
||
|
+ /* 1072 */ U128 guest_VSR59;
|
||
|
+ /* 1088 */ U128 guest_VSR60;
|
||
|
+ /* 1104 */ U128 guest_VSR61;
|
||
|
+ /* 1120 */ U128 guest_VSR62;
|
||
|
+ /* 1136 */ U128 guest_VSR63;
|
||
|
+
|
||
|
+ /* 1152 */ UInt guest_CIA; // IP (no arch visible register)
|
||
|
+ /* 1156 */ UInt guest_LR; // Link Register
|
||
|
+ /* 1160 */ UInt guest_CTR; // Count Register
|
||
|
|
||
|
/* XER pieces */
|
||
|
- /* 908 */ UChar guest_XER_SO; /* in lsb */
|
||
|
- /* 909 */ UChar guest_XER_OV; /* in lsb */
|
||
|
- /* 910 */ UChar guest_XER_CA; /* in lsb */
|
||
|
- /* 911 */ UChar guest_XER_BC; /* all bits */
|
||
|
+ /* 1164 */ UChar guest_XER_SO; /* in lsb */
|
||
|
+ /* 1165 */ UChar guest_XER_OV; /* in lsb */
|
||
|
+ /* 1166 */ UChar guest_XER_CA; /* in lsb */
|
||
|
+ /* 1167 */ UChar guest_XER_BC; /* all bits */
|
||
|
|
||
|
/* CR pieces */
|
||
|
- /* 912 */ UChar guest_CR0_321; /* in [3:1] */
|
||
|
- /* 913 */ UChar guest_CR0_0; /* in lsb */
|
||
|
- /* 914 */ UChar guest_CR1_321; /* in [3:1] */
|
||
|
- /* 915 */ UChar guest_CR1_0; /* in lsb */
|
||
|
- /* 916 */ UChar guest_CR2_321; /* in [3:1] */
|
||
|
- /* 917 */ UChar guest_CR2_0; /* in lsb */
|
||
|
- /* 918 */ UChar guest_CR3_321; /* in [3:1] */
|
||
|
- /* 919 */ UChar guest_CR3_0; /* in lsb */
|
||
|
- /* 920 */ UChar guest_CR4_321; /* in [3:1] */
|
||
|
- /* 921 */ UChar guest_CR4_0; /* in lsb */
|
||
|
- /* 922 */ UChar guest_CR5_321; /* in [3:1] */
|
||
|
- /* 923 */ UChar guest_CR5_0; /* in lsb */
|
||
|
- /* 924 */ UChar guest_CR6_321; /* in [3:1] */
|
||
|
- /* 925 */ UChar guest_CR6_0; /* in lsb */
|
||
|
- /* 926 */ UChar guest_CR7_321; /* in [3:1] */
|
||
|
- /* 927 */ UChar guest_CR7_0; /* in lsb */
|
||
|
+ /* 1168 */ UChar guest_CR0_321; /* in [3:1] */
|
||
|
+ /* 1169 */ UChar guest_CR0_0; /* in lsb */
|
||
|
+ /* 1170 */ UChar guest_CR1_321; /* in [3:1] */
|
||
|
+ /* 1171 */ UChar guest_CR1_0; /* in lsb */
|
||
|
+ /* 1172 */ UChar guest_CR2_321; /* in [3:1] */
|
||
|
+ /* 1173 */ UChar guest_CR2_0; /* in lsb */
|
||
|
+ /* 1174 */ UChar guest_CR3_321; /* in [3:1] */
|
||
|
+ /* 1175 */ UChar guest_CR3_0; /* in lsb */
|
||
|
+ /* 1176 */ UChar guest_CR4_321; /* in [3:1] */
|
||
|
+ /* 1177 */ UChar guest_CR4_0; /* in lsb */
|
||
|
+ /* 1178 */ UChar guest_CR5_321; /* in [3:1] */
|
||
|
+ /* 1179 */ UChar guest_CR5_0; /* in lsb */
|
||
|
+ /* 1180 */ UChar guest_CR6_321; /* in [3:1] */
|
||
|
+ /* 1181 */ UChar guest_CR6_0; /* in lsb */
|
||
|
+ /* 1182 */ UChar guest_CR7_321; /* in [3:1] */
|
||
|
+ /* 1183 */ UChar guest_CR7_0; /* in lsb */
|
||
|
|
||
|
/* FP Status & Control Register fields */
|
||
|
- /* 928 */ UInt guest_FPROUND; // FP Rounding Mode
|
||
|
+ /* 1184 */ UInt guest_FPROUND; // FP Rounding Mode
|
||
|
|
||
|
/* Vector Save/Restore Register */
|
||
|
- /* 932 */ UInt guest_VRSAVE;
|
||
|
+ /* 1188 */ UInt guest_VRSAVE;
|
||
|
|
||
|
/* Vector Status and Control Register */
|
||
|
- /* 936 */ UInt guest_VSCR;
|
||
|
+ /* 1192 */ UInt guest_VSCR;
|
||
|
|
||
|
/* Emulation warnings */
|
||
|
- /* 940 */ UInt guest_EMWARN;
|
||
|
+ /* 1196 */ UInt guest_EMWARN;
|
||
|
|
||
|
/* For icbi: record start and length of area to invalidate */
|
||
|
- /* 944 */ UInt guest_TISTART;
|
||
|
- /* 948 */ UInt guest_TILEN;
|
||
|
+ /* 1200 */ UInt guest_TISTART;
|
||
|
+ /* 1204 */ UInt guest_TILEN;
|
||
|
|
||
|
/* Used to record the unredirected guest address at the start of
|
||
|
a translation whose start has been redirected. By reading
|
||
|
@@ -203,27 +211,27 @@ typedef
|
||
|
find out what the corresponding no-redirection address was.
|
||
|
Note, this is only set for wrap-style redirects, not for
|
||
|
replace-style ones. */
|
||
|
- /* 952 */ UInt guest_NRADDR;
|
||
|
- /* 956 */ UInt guest_NRADDR_GPR2; /* needed by aix */
|
||
|
+ /* 1208 */ UInt guest_NRADDR;
|
||
|
+ /* 1212 */ UInt guest_NRADDR_GPR2; /* needed by aix */
|
||
|
|
||
|
/* A grows-upwards stack for hidden saves/restores of LR and R2
|
||
|
needed for function interception and wrapping on ppc32-aix5.
|
||
|
A horrible hack. REDIR_SP points to the highest live entry,
|
||
|
and so starts at -1. */
|
||
|
- /* 960 */ UInt guest_REDIR_SP;
|
||
|
- /* 964 */ UInt guest_REDIR_STACK[VEX_GUEST_PPC32_REDIR_STACK_SIZE];
|
||
|
+ /* 1216 */ UInt guest_REDIR_SP;
|
||
|
+ /* 1220 */ UInt guest_REDIR_STACK[VEX_GUEST_PPC32_REDIR_STACK_SIZE];
|
||
|
|
||
|
/* Needed for AIX (but mandated for all guest architectures):
|
||
|
CIA at the last SC insn. Used when backing up to restart a
|
||
|
syscall that has been interrupted by a signal. */
|
||
|
- /* ??? */ UInt guest_IP_AT_SYSCALL;
|
||
|
+ /* 1348 */ UInt guest_IP_AT_SYSCALL;
|
||
|
|
||
|
/* SPRG3, which AIUI is readonly in user space. Needed for
|
||
|
threading on AIX. */
|
||
|
- /* ??? */ UInt guest_SPRG3_RO;
|
||
|
+ /* 1352 */ UInt guest_SPRG3_RO;
|
||
|
|
||
|
/* Padding to make it have an 8-aligned size */
|
||
|
- /* UInt padding; */
|
||
|
+ /* 1356 */ UInt padding;
|
||
|
}
|
||
|
VexGuestPPC32State;
|
||
|
|
||
|
Index: VEX/pub/libvex_guest_ppc64.h
|
||
|
===================================================================
|
||
|
--- VEX/pub/libvex_guest_ppc64.h.orig
|
||
|
+++ VEX/pub/libvex_guest_ppc64.h
|
||
|
@@ -120,123 +120,131 @@ typedef
|
||
|
/* 240 */ ULong guest_GPR30;
|
||
|
/* 248 */ ULong guest_GPR31;
|
||
|
|
||
|
- // Floating Point Registers
|
||
|
- /* 256 */ ULong guest_FPR0;
|
||
|
- /* 264 */ ULong guest_FPR1;
|
||
|
- /* 272 */ ULong guest_FPR2;
|
||
|
- /* 280 */ ULong guest_FPR3;
|
||
|
- /* 288 */ ULong guest_FPR4;
|
||
|
- /* 296 */ ULong guest_FPR5;
|
||
|
- /* 304 */ ULong guest_FPR6;
|
||
|
- /* 312 */ ULong guest_FPR7;
|
||
|
- /* 320 */ ULong guest_FPR8;
|
||
|
- /* 328 */ ULong guest_FPR9;
|
||
|
- /* 336 */ ULong guest_FPR10;
|
||
|
- /* 344 */ ULong guest_FPR11;
|
||
|
- /* 352 */ ULong guest_FPR12;
|
||
|
- /* 360 */ ULong guest_FPR13;
|
||
|
- /* 368 */ ULong guest_FPR14;
|
||
|
- /* 376 */ ULong guest_FPR15;
|
||
|
- /* 384 */ ULong guest_FPR16;
|
||
|
- /* 392 */ ULong guest_FPR17;
|
||
|
- /* 400 */ ULong guest_FPR18;
|
||
|
- /* 408 */ ULong guest_FPR19;
|
||
|
- /* 416 */ ULong guest_FPR20;
|
||
|
- /* 424 */ ULong guest_FPR21;
|
||
|
- /* 432 */ ULong guest_FPR22;
|
||
|
- /* 440 */ ULong guest_FPR23;
|
||
|
- /* 448 */ ULong guest_FPR24;
|
||
|
- /* 456 */ ULong guest_FPR25;
|
||
|
- /* 464 */ ULong guest_FPR26;
|
||
|
- /* 472 */ ULong guest_FPR27;
|
||
|
- /* 480 */ ULong guest_FPR28;
|
||
|
- /* 488 */ ULong guest_FPR29;
|
||
|
- /* 496 */ ULong guest_FPR30;
|
||
|
- /* 504 */ ULong guest_FPR31;
|
||
|
+ // Vector Registers, Floating Point Registers, and VSX Registers
|
||
|
+ // With ISA 2.06, the "Vector-Scalar Floating-point" category
|
||
|
+ // provides facilities to support vector and scalar binary floating-
|
||
|
+ // point operations. A unified register file is an integral part
|
||
|
+ // of this new facility, combining floating point and vector registers
|
||
|
+ // using a 64x128-bit vector. These are referred to as VSR[0..63].
|
||
|
+ // The floating point registers are now mapped into double word element 0
|
||
|
+ // of VSR[0..31]. The 32x128-bit vector registers defined by the "Vector
|
||
|
+ // Facility [Category: Vector]" are now mapped to VSR[32..63].
|
||
|
|
||
|
- // Vector Registers
|
||
|
// IMPORTANT: the user of libvex must place the guest state so as
|
||
|
- // to ensure that guest_VR{0..31}, and any shadows thereof, are
|
||
|
+ // to ensure that guest_VSR{0..63}, and any shadows thereof, are
|
||
|
// 16-aligned.
|
||
|
- /* 512 */ U128 guest_VR0;
|
||
|
- /* 528 */ U128 guest_VR1;
|
||
|
- /* 544 */ U128 guest_VR2;
|
||
|
- /* 560 */ U128 guest_VR3;
|
||
|
- /* 576 */ U128 guest_VR4;
|
||
|
- /* 592 */ U128 guest_VR5;
|
||
|
- /* 608 */ U128 guest_VR6;
|
||
|
- /* 624 */ U128 guest_VR7;
|
||
|
- /* 640 */ U128 guest_VR8;
|
||
|
- /* 656 */ U128 guest_VR9;
|
||
|
- /* 672 */ U128 guest_VR10;
|
||
|
- /* 688 */ U128 guest_VR11;
|
||
|
- /* 704 */ U128 guest_VR12;
|
||
|
- /* 720 */ U128 guest_VR13;
|
||
|
- /* 736 */ U128 guest_VR14;
|
||
|
- /* 752 */ U128 guest_VR15;
|
||
|
- /* 768 */ U128 guest_VR16;
|
||
|
- /* 784 */ U128 guest_VR17;
|
||
|
- /* 800 */ U128 guest_VR18;
|
||
|
- /* 816 */ U128 guest_VR19;
|
||
|
- /* 832 */ U128 guest_VR20;
|
||
|
- /* 848 */ U128 guest_VR21;
|
||
|
- /* 864 */ U128 guest_VR22;
|
||
|
- /* 880 */ U128 guest_VR23;
|
||
|
- /* 896 */ U128 guest_VR24;
|
||
|
- /* 912 */ U128 guest_VR25;
|
||
|
- /* 928 */ U128 guest_VR26;
|
||
|
- /* 944 */ U128 guest_VR27;
|
||
|
- /* 960 */ U128 guest_VR28;
|
||
|
- /* 976 */ U128 guest_VR29;
|
||
|
- /* 992 */ U128 guest_VR30;
|
||
|
- /* 1008 */ U128 guest_VR31;
|
||
|
-
|
||
|
- /* 1024 */ ULong guest_CIA; // IP (no arch visible register)
|
||
|
- /* 1032 */ ULong guest_LR; // Link Register
|
||
|
- /* 1040 */ ULong guest_CTR; // Count Register
|
||
|
+
|
||
|
+ /* 256 */ U128 guest_VSR0;
|
||
|
+ /* 272 */ U128 guest_VSR1;
|
||
|
+ /* 288 */ U128 guest_VSR2;
|
||
|
+ /* 304 */ U128 guest_VSR3;
|
||
|
+ /* 320 */ U128 guest_VSR4;
|
||
|
+ /* 336 */ U128 guest_VSR5;
|
||
|
+ /* 352 */ U128 guest_VSR6;
|
||
|
+ /* 368 */ U128 guest_VSR7;
|
||
|
+ /* 384 */ U128 guest_VSR8;
|
||
|
+ /* 400 */ U128 guest_VSR9;
|
||
|
+ /* 416 */ U128 guest_VSR10;
|
||
|
+ /* 432 */ U128 guest_VSR11;
|
||
|
+ /* 448 */ U128 guest_VSR12;
|
||
|
+ /* 464 */ U128 guest_VSR13;
|
||
|
+ /* 480 */ U128 guest_VSR14;
|
||
|
+ /* 496 */ U128 guest_VSR15;
|
||
|
+ /* 512 */ U128 guest_VSR16;
|
||
|
+ /* 528 */ U128 guest_VSR17;
|
||
|
+ /* 544 */ U128 guest_VSR18;
|
||
|
+ /* 560 */ U128 guest_VSR19;
|
||
|
+ /* 576 */ U128 guest_VSR20;
|
||
|
+ /* 592 */ U128 guest_VSR21;
|
||
|
+ /* 608 */ U128 guest_VSR22;
|
||
|
+ /* 624 */ U128 guest_VSR23;
|
||
|
+ /* 640 */ U128 guest_VSR24;
|
||
|
+ /* 656 */ U128 guest_VSR25;
|
||
|
+ /* 672 */ U128 guest_VSR26;
|
||
|
+ /* 688 */ U128 guest_VSR27;
|
||
|
+ /* 704 */ U128 guest_VSR28;
|
||
|
+ /* 720 */ U128 guest_VSR29;
|
||
|
+ /* 736 */ U128 guest_VSR30;
|
||
|
+ /* 752 */ U128 guest_VSR31;
|
||
|
+ /* 768 */ U128 guest_VSR32;
|
||
|
+ /* 784 */ U128 guest_VSR33;
|
||
|
+ /* 800 */ U128 guest_VSR34;
|
||
|
+ /* 816 */ U128 guest_VSR35;
|
||
|
+ /* 832 */ U128 guest_VSR36;
|
||
|
+ /* 848 */ U128 guest_VSR37;
|
||
|
+ /* 864 */ U128 guest_VSR38;
|
||
|
+ /* 880 */ U128 guest_VSR39;
|
||
|
+ /* 896 */ U128 guest_VSR40;
|
||
|
+ /* 912 */ U128 guest_VSR41;
|
||
|
+ /* 928 */ U128 guest_VSR42;
|
||
|
+ /* 944 */ U128 guest_VSR43;
|
||
|
+ /* 960 */ U128 guest_VSR44;
|
||
|
+ /* 976 */ U128 guest_VSR45;
|
||
|
+ /* 992 */ U128 guest_VSR46;
|
||
|
+ /* 1008 */ U128 guest_VSR47;
|
||
|
+ /* 1024 */ U128 guest_VSR48;
|
||
|
+ /* 1040 */ U128 guest_VSR49;
|
||
|
+ /* 1056 */ U128 guest_VSR50;
|
||
|
+ /* 1072 */ U128 guest_VSR51;
|
||
|
+ /* 1088 */ U128 guest_VSR52;
|
||
|
+ /* 1104 */ U128 guest_VSR53;
|
||
|
+ /* 1120 */ U128 guest_VSR54;
|
||
|
+ /* 1136 */ U128 guest_VSR55;
|
||
|
+ /* 1152 */ U128 guest_VSR56;
|
||
|
+ /* 1168 */ U128 guest_VSR57;
|
||
|
+ /* 1184 */ U128 guest_VSR58;
|
||
|
+ /* 1200 */ U128 guest_VSR59;
|
||
|
+ /* 1216 */ U128 guest_VSR60;
|
||
|
+ /* 1232 */ U128 guest_VSR61;
|
||
|
+ /* 1248 */ U128 guest_VSR62;
|
||
|
+ /* 1264 */ U128 guest_VSR63;
|
||
|
+
|
||
|
+ /* 1280 */ ULong guest_CIA; // IP (no arch visible register)
|
||
|
+ /* 1288 */ ULong guest_LR; // Link Register
|
||
|
+ /* 1296 */ ULong guest_CTR; // Count Register
|
||
|
|
||
|
/* XER pieces */
|
||
|
- /* 1048 */ UChar guest_XER_SO; /* in lsb */
|
||
|
- /* 1049 */ UChar guest_XER_OV; /* in lsb */
|
||
|
- /* 1050 */ UChar guest_XER_CA; /* in lsb */
|
||
|
- /* 1051 */ UChar guest_XER_BC; /* all bits */
|
||
|
+ /* 1304 */ UChar guest_XER_SO; /* in lsb */
|
||
|
+ /* 1305 */ UChar guest_XER_OV; /* in lsb */
|
||
|
+ /* 1306 */ UChar guest_XER_CA; /* in lsb */
|
||
|
+ /* 1307 */ UChar guest_XER_BC; /* all bits */
|
||
|
|
||
|
/* CR pieces */
|
||
|
- /* 1052 */ UChar guest_CR0_321; /* in [3:1] */
|
||
|
- /* 1053 */ UChar guest_CR0_0; /* in lsb */
|
||
|
- /* 1054 */ UChar guest_CR1_321; /* in [3:1] */
|
||
|
- /* 1055 */ UChar guest_CR1_0; /* in lsb */
|
||
|
- /* 1056 */ UChar guest_CR2_321; /* in [3:1] */
|
||
|
- /* 1057 */ UChar guest_CR2_0; /* in lsb */
|
||
|
- /* 1058 */ UChar guest_CR3_321; /* in [3:1] */
|
||
|
- /* 1059 */ UChar guest_CR3_0; /* in lsb */
|
||
|
- /* 1060 */ UChar guest_CR4_321; /* in [3:1] */
|
||
|
- /* 1061 */ UChar guest_CR4_0; /* in lsb */
|
||
|
- /* 1062 */ UChar guest_CR5_321; /* in [3:1] */
|
||
|
- /* 1063 */ UChar guest_CR5_0; /* in lsb */
|
||
|
- /* 1064 */ UChar guest_CR6_321; /* in [3:1] */
|
||
|
- /* 1065 */ UChar guest_CR6_0; /* in lsb */
|
||
|
- /* 1066 */ UChar guest_CR7_321; /* in [3:1] */
|
||
|
- /* 1067 */ UChar guest_CR7_0; /* in lsb */
|
||
|
+ /* 1308 */ UChar guest_CR0_321; /* in [3:1] */
|
||
|
+ /* 1309 */ UChar guest_CR0_0; /* in lsb */
|
||
|
+ /* 1310 */ UChar guest_CR1_321; /* in [3:1] */
|
||
|
+ /* 1311 */ UChar guest_CR1_0; /* in lsb */
|
||
|
+ /* 1312 */ UChar guest_CR2_321; /* in [3:1] */
|
||
|
+ /* 1313 */ UChar guest_CR2_0; /* in lsb */
|
||
|
+ /* 1314 */ UChar guest_CR3_321; /* in [3:1] */
|
||
|
+ /* 1315 */ UChar guest_CR3_0; /* in lsb */
|
||
|
+ /* 1316 */ UChar guest_CR4_321; /* in [3:1] */
|
||
|
+ /* 1317 */ UChar guest_CR4_0; /* in lsb */
|
||
|
+ /* 1318 */ UChar guest_CR5_321; /* in [3:1] */
|
||
|
+ /* 1319 */ UChar guest_CR5_0; /* in lsb */
|
||
|
+ /* 1320 */ UChar guest_CR6_321; /* in [3:1] */
|
||
|
+ /* 1321 */ UChar guest_CR6_0; /* in lsb */
|
||
|
+ /* 1322 */ UChar guest_CR7_321; /* in [3:1] */
|
||
|
+ /* 1323 */ UChar guest_CR7_0; /* in lsb */
|
||
|
|
||
|
/* FP Status & Control Register fields */
|
||
|
- /* 1068 */ UInt guest_FPROUND; // FP Rounding Mode
|
||
|
+ /* 1324 */ UInt guest_FPROUND; // FP Rounding Mode
|
||
|
|
||
|
/* Vector Save/Restore Register */
|
||
|
- /* 1072 */ UInt guest_VRSAVE;
|
||
|
+ /* 1328 */ UInt guest_VRSAVE;
|
||
|
|
||
|
/* Vector Status and Control Register */
|
||
|
- /* 1076 */ UInt guest_VSCR;
|
||
|
+ /* 1332 */ UInt guest_VSCR;
|
||
|
|
||
|
/* Emulation warnings */
|
||
|
- /* 1080 */ UInt guest_EMWARN;
|
||
|
+ /* 1336 */ UInt guest_EMWARN;
|
||
|
|
||
|
/* gcc adds 4 bytes padding here: pre-empt it. */
|
||
|
- /* 1084 */ UInt padding;
|
||
|
+ /* 1340 */ UInt padding;
|
||
|
|
||
|
/* For icbi: record start and length of area to invalidate */
|
||
|
- /* 1088 */ ULong guest_TISTART;
|
||
|
- /* 1096 */ ULong guest_TILEN;
|
||
|
+ /* 1344 */ ULong guest_TISTART;
|
||
|
+ /* 1352 */ ULong guest_TILEN;
|
||
|
|
||
|
/* Used to record the unredirected guest address at the start of
|
||
|
a translation whose start has been redirected. By reading
|
||
|
@@ -244,26 +252,26 @@ typedef
|
||
|
find out what the corresponding no-redirection address was.
|
||
|
Note, this is only set for wrap-style redirects, not for
|
||
|
replace-style ones. */
|
||
|
- /* 1104 */ ULong guest_NRADDR;
|
||
|
- /* 1112 */ ULong guest_NRADDR_GPR2;
|
||
|
+ /* 1360 */ ULong guest_NRADDR;
|
||
|
+ /* 1368 */ ULong guest_NRADDR_GPR2;
|
||
|
|
||
|
/* A grows-upwards stack for hidden saves/restores of LR and R2
|
||
|
needed for function interception and wrapping on ppc64-linux.
|
||
|
A horrible hack. REDIR_SP points to the highest live entry,
|
||
|
and so starts at -1. */
|
||
|
- /* 1120 */ ULong guest_REDIR_SP;
|
||
|
- /* 1128 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE];
|
||
|
+ /* 1376 */ ULong guest_REDIR_SP;
|
||
|
+ /* 1384 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE];
|
||
|
|
||
|
/* Needed for AIX: CIA at the last SC insn. Used when backing up
|
||
|
to restart a syscall that has been interrupted by a signal. */
|
||
|
- /* 1384 */ ULong guest_IP_AT_SYSCALL;
|
||
|
+ /* 1640 */ ULong guest_IP_AT_SYSCALL;
|
||
|
|
||
|
/* SPRG3, which AIUI is readonly in user space. Needed for
|
||
|
threading on AIX. */
|
||
|
- /* ???? */ ULong guest_SPRG3_RO;
|
||
|
+ /* 1648 */ ULong guest_SPRG3_RO;
|
||
|
|
||
|
- /* Padding to make it have an 8-aligned size */
|
||
|
- /* ???? */ ULong padding2;
|
||
|
+ /* Padding to make it have an 16-aligned size */
|
||
|
+ /* 1656 */ ULong padding2;
|
||
|
}
|
||
|
VexGuestPPC64State;
|
||
|
|
||
|
Index: VEX/pub/libvex.h
|
||
|
===================================================================
|
||
|
--- VEX/pub/libvex.h.orig
|
||
|
+++ VEX/pub/libvex.h
|
||
|
@@ -87,12 +87,14 @@ typedef
|
||
|
#define VEX_HWCAPS_PPC32_FX (1<<10) /* FP extns (fsqrt, fsqrts) */
|
||
|
#define VEX_HWCAPS_PPC32_GX (1<<11) /* Graphics extns
|
||
|
(fres,frsqrte,fsel,stfiwx) */
|
||
|
+#define VEX_HWCAPS_PPC32_VX (1<<12) /* Vector-scalar floating-point (VSX); implies ISA 2.06 or higher */
|
||
|
|
||
|
/* ppc64: baseline capability is integer and basic FP insns */
|
||
|
-#define VEX_HWCAPS_PPC64_V (1<<12) /* Altivec (VMX) */
|
||
|
-#define VEX_HWCAPS_PPC64_FX (1<<13) /* FP extns (fsqrt, fsqrts) */
|
||
|
-#define VEX_HWCAPS_PPC64_GX (1<<14) /* Graphics extns
|
||
|
+#define VEX_HWCAPS_PPC64_V (1<<13) /* Altivec (VMX) */
|
||
|
+#define VEX_HWCAPS_PPC64_FX (1<<14) /* FP extns (fsqrt, fsqrts) */
|
||
|
+#define VEX_HWCAPS_PPC64_GX (1<<15) /* Graphics extns
|
||
|
(fres,frsqrte,fsel,stfiwx) */
|
||
|
+#define VEX_HWCAPS_PPC64_VX (1<<16) /* Vector-scalar floating-point (VSX); implies ISA 2.06 or higher */
|
||
|
|
||
|
/* s390x: baseline capability is z/Architecture with long displacement */
|
||
|
#define VEX_HWCAPS_S390X_LDISP (1<<13) /* Long-displacement facility */
|
||
|
Index: VEX/pub/libvex_ir.h
|
||
|
===================================================================
|
||
|
--- VEX/pub/libvex_ir.h.orig
|
||
|
+++ VEX/pub/libvex_ir.h
|
||
|
@@ -616,6 +616,8 @@ typedef
|
||
|
Iop_I16StoF64, /* signed I16 -> F64 */
|
||
|
Iop_I32StoF64, /* signed I32 -> F64 */
|
||
|
Iop_I64StoF64, /* IRRoundingMode(I32) x signed I64 -> F64 */
|
||
|
+ Iop_I64UtoF64, /* IRRoundingMode(I32) x unsigned I64 -> F64 */
|
||
|
+ Iop_I64UtoF32, /* IRRoundingMode(I32) x unsigned I64 -> F32 */
|
||
|
|
||
|
Iop_I32UtoF64, /* unsigned I32 -> F64 */
|
||
|
|