UChar vB_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */
UInt opc2 = (theInstr >> 0) & 0x7FF; /* theInstr[0:10] */
+ IRTemp vA = newTemp(Ity_V128);
+ IRTemp vB = newTemp(Ity_V128);
+ assign( vA, getVReg(vA_addr));
+ assign( vB, getVReg(vB_addr));
+
if (opc1 != 0x4) {
vex_printf("dis_av_arith(PPC32)(opc1 != 0x4)\n");
return False;
switch (opc2) {
/* Add */
- case 0x180: // vaddcuw (Add Carryout Unsigned Word, AV p136)
+ case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
- DIP(" => not implemented\n");
- return False;
-
+ /* ov = x >u (x+y) */
+ IRTemp sum = newTemp(Ity_V128);
+ assign( sum, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
+ putVReg( vD_addr, binop(Iop_ShrN32x4,
+ binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(sum)),
+ mkU8(31)) );
+ break;
+ }
case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
DIP(" => not implemented\n");
HReg v2 = newVRegV(env);
addInstr(env, PPC32Instr_AvSplat(sz, v1, PPC32VI5s_Imm(-16)));
addInstr(env, PPC32Instr_AvSplat(sz, v2, PPC32VI5s_Imm(simm6-16)));
- addInstr(env, PPC32Instr_AvBinary(Pav_SUBUM, dst, v2, v1));
+ addInstr(env,
+ (sz== 8) ? PPC32Instr_AvBin8x16(Pav_SUBUM, dst, v2, v1) :
+ (sz==16) ? PPC32Instr_AvBin16x8(Pav_SUBUM, dst, v2, v1)
+ : PPC32Instr_AvBin32x4(Pav_SUBUM, dst, v2, v1) );
return dst;
}
if (simm6 < -16) { /* -32:-17 inclusive */
HReg v2 = newVRegV(env);
addInstr(env, PPC32Instr_AvSplat(sz, v1, PPC32VI5s_Imm(-16)));
addInstr(env, PPC32Instr_AvSplat(sz, v2, PPC32VI5s_Imm(simm6+16)));
- addInstr(env, PPC32Instr_AvBinary(Pav_ADDUM, dst, v2, v1));
+ addInstr(env,
+ (sz== 8) ? PPC32Instr_AvBin8x16(Pav_ADDUM, dst, v2, v1) :
+ (sz==16) ? PPC32Instr_AvBin16x8(Pav_ADDUM, dst, v2, v1)
+ : PPC32Instr_AvBin32x4(Pav_ADDUM, dst, v2, v1) );
return dst;
}
/* simplest form: -16:15 inclusive */
addInstr(env, PPC32Instr_AvBinary(op, dst, arg1, arg2));
return dst;
}
+
+ case Iop_Add32x4: op = Pav_ADDUM; goto do_AvBin32x4;
+ case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
+ do_AvBin32x4: {
+ HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
+ HReg dst = newVRegV(env);
+ addInstr(env, PPC32Instr_AvBin32x4(op, dst, arg1, arg2));
+ return dst;
+ }
+
//.. do_SseReRg: {
//.. HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
//.. HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
//.. case Iop_SarN16x8: op = Xsse_SAR16; goto do_SseShift;
//.. case Iop_SarN32x4: op = Xsse_SAR32; goto do_SseShift;
//.. case Iop_ShrN16x8: op = Xsse_SHR16; goto do_SseShift;
-//.. case Iop_ShrN32x4: op = Xsse_SHR32; goto do_SseShift;
//.. case Iop_ShrN64x2: op = Xsse_SHR64; goto do_SseShift;
+ case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
+ do_AvShift32x4: {
+ HReg r_src = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg dst = newVRegV(env);
+ HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
+ addInstr(env, PPC32Instr_AvBin32x4(op, dst, r_src, v_shft));
+ return dst;
+ }
+
case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
do_AvShiftV128: {
HReg dst = newVRegV(env);