const opnd_t *result = &data->result;
const opnd_t *opnd1 = &data->opnds[0];
const opnd_t *opnd2 = &data->opnds[1];
+ opnd_t tmp;
vbits_t expected_vbits;
/* Only handle those undef-kinds that actually occur. */
break;
case UNDEF_ALL:
+ /* Iop_ShlD64, Iop_ShrD64, Iop_ShlD128, Iop_ShrD128 have
+ * one immediate operand in operand 2.
+ */
expected_vbits = undefined_vbits(result->vbits.num_bits);
break;
opnd2->vbits.num_bits);
break;
+ case UNDEF_ALL_64x2:
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(64, 2,
+ or_vbits(opnd1->vbits, opnd2->vbits));
+ break;
+
+ case UNDEF_ALL_32x4:
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(32, 4,
+ or_vbits(opnd1->vbits, opnd2->vbits));
+ break;
+
+ case UNDEF_ALL_16x8:
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(16, 8,
+ or_vbits(opnd1->vbits, opnd2->vbits));
+ break;
+
+ case UNDEF_ALL_8x16:
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(8, 16,
+ or_vbits(opnd1->vbits, opnd2->vbits));
+ break;
+
+ case UNDEF_ALL_32x4_EVEN:
+ /* Only even input bytes are used, result can be twice as wide */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(64, 2,
+ undefined_vbits_128_even_element(32, 4,
+ or_vbits(opnd1->vbits, opnd2->vbits)));
+ break;
+
+ case UNDEF_ALL_16x8_EVEN:
+ /* Only even input bytes are used, result can be twice as wide */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(32, 4,
+ undefined_vbits_128_even_element(16, 8,
+ or_vbits(opnd1->vbits, opnd2->vbits)));
+ break;
+
+ case UNDEF_ALL_8x16_EVEN:
+ /* Only even input bytes are used, result can be twice as wide */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits =
+ undefined_vbits_BxE(16, 8,
+ undefined_vbits_128_even_element(8, 16,
+ or_vbits(opnd1->vbits, opnd2->vbits)));
+ break;
+
+ case UNDEF_64x2_ROTATE:
+ /* Rotate left each element in opnd1 by the amount in the corresponding
+ * element of opnd2.
+ */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ /* Setup the tmp to match what the vbit tester seems to use. I can't
+ * use opnd2-value since valgrind doesn't think it has been set.
+ */
+ tmp.value.u128[0] = -1;
+ tmp.value.u128[1] = -1;
+ /* Calculate expected for the first operand when it is shifted.
+ * If any of the vbits are set for the shift field of the second operand
+ * then the result of the expected result for that element is all 1's.
+ */
+ expected_vbits = or_vbits(undefined_vbits_BxE_rotate(64, 2, opnd1->vbits,
+ tmp.value),
+ undefined_vbits_BxE(64, 2, opnd2->vbits));
+ break;
+
+ case UNDEF_32x4_ROTATE:
+ /* Rotate left each element in opnd1 by the amount in the corresponding
+ * element of opnd2.
+ */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits = undefined_vbits_BxE_rotate(32, 4, opnd1->vbits,
+ opnd2->value);
+ break;
+
+ case UNDEF_16x8_ROTATE:
+ /* Rotate left each element in opnd1 by the amount in the corresponding
+ * element of opnd2.
+ */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits = undefined_vbits_BxE_rotate(16, 8, opnd1->vbits,
+ opnd2->value);
+ break;
+
+ case UNDEF_8x16_ROTATE:
+ /* Rotate left each element in opnd1 by the amount in the corresponding
+ * element of opnd2.
+ */
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ expected_vbits = undefined_vbits_BxE_rotate(16, 8, opnd1->vbits,
+ opnd2->value);
+ break;
+
+ case UNDEF_SOME:
+ /* The result for the Iop_SHA256 and Iop_SHA256 is a secure hash. If
+ * one of the input bits is not defined there must be atleast one
+ * undefined bit in the output. Which bit and how many depends on
+ * which bit is undefined. Don't know the secure hash algorithm so
+ * we can only make sure at least one of the result bits is set.
+ *
+ * The Iop_SHA256, Iop_SHA512 iops have one immediate value in the
+ * second operand.
+ */
+ expected_vbits.num_bits = result->vbits.num_bits;
+
+ if ((result->vbits.bits.u128[0] != 0) ||
+ (result->vbits.bits.u128[1] != 0)) {
+ expected_vbits.bits.u128[0] = result->vbits.bits.u128[0];
+ expected_vbits.bits.u128[1] = result->vbits.bits.u128[1];
+
+ } else {
+ /* The input had at least one vbit set but the result doesn't have any
+ * bit set. Set them all so we will trigger the error on the call
+ * to complain().
+ */
+ expected_vbits.bits.u128[0] = ~0x0ULL;
+ expected_vbits.bits.u128[1] = ~0x0ULL;
+ }
+ break;
+
+ case UNDEF_NARROW256_AtoB:
+ assert(opnd1->vbits.num_bits == opnd2->vbits.num_bits);
+ switch(op->op) {
+ case Iop_NarrowBin64to32x4:
+ expected_vbits =
+ undefined_vbits_Narrow256_AtoB(64, 32, opnd1->vbits, opnd1->value,
+ opnd2->vbits, opnd2->value,
+ False);
+ break;
+ case Iop_QNarrowBin64Sto32Sx4:
+ expected_vbits =
+ undefined_vbits_Narrow256_AtoB(64, 32, opnd1->vbits, opnd1->value,
+ opnd2->vbits, opnd2->value,
+ True);
+ break;
+ case Iop_QNarrowBin64Uto32Ux4:
+ expected_vbits =
+ undefined_vbits_Narrow256_AtoB(64, 32, opnd1->vbits, opnd1->value,
+ opnd2->vbits, opnd2->value,
+ True);
+ break;
+ default:
+ fprintf(stderr, "ERROR, unknown Iop for UNDEF_NARROW256_AtoB\n");
+ panic(__func__);
+ }
+ break;
+
default:
panic(__func__);
}
// 2nd (right) operand
/* If the operand is an immediate value, there are no v-bits to set. */
- if (op->shift_amount_is_immediate) return tests_done;
+ if (!op->immediate_index) return tests_done;
num_input_bits = bitsof_irtype(opnds[1].type);
operand. */
for (i = 0; i < 2; ++i) {
- /* If this is a shift op that requires an immediate shift amount,
- do not iterate the v-bits of the 2nd operand */
- if (i == 1 && op->shift_amount_is_immediate) break;
+ /* If this is a Iop that requires an immediate amount,
+ do not iterate the v-bits of the operand */
+ if (((i+1) == op->immediate_index)
+ && (op->immediate_index)) break;
num_input_bits = bitsof_irtype(opnds[i].type);
opnds[0].vbits = defined_vbits(bitsof_irtype(opnds[0].type));
assert(sizeof xx.v1 == sizeof xx.v2.u64);
assert(xx.v1 == xx.v2.u64);
*/
- if (op->shift_amount_is_immediate)
+
+ if (op->immediate_index > 0) {
+ assert((op->immediate_type == Ity_I8)
+ || (op->immediate_type == Ity_I16)
+ || (op->immediate_type == Ity_I32));
opnds[1].value.u64 = 1;
+ }
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
opnds[i].vbits = onehot_vbits(bitpos, bitsof_irtype(opnds[i].type));
+
/* -*- mode: C; c-basic-offset: 3; -*- */
/*
{ DEFOP(Iop_MulHi32Ux4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_MulHi16Sx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_MulHi32Sx4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven8Ux16, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven16Ux8, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven32Ux4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven8Sx16, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven16Sx8, UNDEF_UNKNOWN), },
- { DEFOP(Iop_MullEven32Sx4, UNDEF_UNKNOWN), },
+ /* Result of the Iop_MullEvenBxE is 2*BxE/2 */
+ { DEFOP(Iop_MullEven8Ux16, UNDEF_ALL_8x16_EVEN), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_MullEven16Ux8, UNDEF_ALL_16x8_EVEN), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_MullEven32Ux4, UNDEF_ALL_32x4_EVEN), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_MullEven8Sx16, UNDEF_ALL_8x16_EVEN), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_MullEven16Sx8, UNDEF_ALL_16x8_EVEN), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_MullEven32Sx4, UNDEF_ALL_32x4_EVEN), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Mull8Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Mull8Sx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Mull16Ux4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max8Sx16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max16Sx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max32Sx4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Max64Sx2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Max64Sx2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Max8Ux16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max16Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max32Ux4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Max64Ux2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Max64Ux2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Min8Sx16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min16Sx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min32Sx4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Min64Sx2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Min64Sx2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Min8Ux16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min16Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min32Ux4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Min64Ux2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Min64Ux2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_CmpEQ8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_CmpEQ16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_CmpEQ32x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_CmpGT8Ux16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_CmpGT16Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_CmpGT32Ux4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_CmpGT64Ux2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpGT64Ux2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Cnt8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Clz8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Clz16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Clz32x4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Clz64x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Clz64x2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_Cls8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Cls16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Cls32x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Rol8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Rol16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Rol32x4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_Rol64x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Rol64x2, UNDEF_64x2_ROTATE), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_QShl8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QShl16x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QShl32x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowBin32Uto16Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowBin16to8x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowBin32to16x8, UNDEF_UNKNOWN), },
- { DEFOP(Iop_NarrowBin64to32x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_NarrowBin64to32x4, UNDEF_NARROW256_AtoB), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_NarrowUn16to8x8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowUn32to16x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_NarrowUn64to32x2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn16Sto8Sx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn32Sto16Sx4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn64Sto32Sx2, UNDEF_UNKNOWN), },
- { DEFOP(Iop_QNarrowBin64Sto32Sx4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QNarrowBin64Sto32Sx4, UNDEF_NARROW256_AtoB), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_QNarrowUn16Sto8Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn32Sto16Ux4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn64Sto32Ux2, UNDEF_UNKNOWN), },
- { DEFOP(Iop_QNarrowBin64Uto32Ux4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QNarrowBin64Uto32Ux4, UNDEF_NARROW256_AtoB), .ppc64 = 1, .ppc32 = 1 },
{ DEFOP(Iop_QNarrowUn16Uto8Ux8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn32Uto16Ux4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_QNarrowUn64Uto32Ux2, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min32Fx8, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max64Fx4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min64Fx4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_BCDAdd, UNDEF_UNKNOWN), },
- { DEFOP(Iop_BCDSub, UNDEF_UNKNOWN), },
- { DEFOP(Iop_PolynomialMulAdd8x16, UNDEF_UNKNOWN), },
- { DEFOP(Iop_PolynomialMulAdd16x8, UNDEF_UNKNOWN), },
- { DEFOP(Iop_PolynomialMulAdd32x4, UNDEF_UNKNOWN), },
- { DEFOP(Iop_PolynomialMulAdd64x2, UNDEF_UNKNOWN), },
- { DEFOP(Iop_CipherV128, UNDEF_UNKNOWN), },
- { DEFOP(Iop_CipherLV128, UNDEF_UNKNOWN), },
- { DEFOP(Iop_CipherSV128, UNDEF_UNKNOWN), },
- { DEFOP(Iop_NCipherV128, UNDEF_UNKNOWN), },
- { DEFOP(Iop_NCipherLV128, UNDEF_UNKNOWN), },
- { DEFOP(Iop_SHA512, UNDEF_UNKNOWN), },
- { DEFOP(Iop_SHA256, UNDEF_UNKNOWN), },
- { DEFOP(Iop_PwBitMtxXpose64x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_BCDAdd, UNDEF_SOME), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_BCDSub, UNDEF_SOME), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_PolynomialMulAdd8x16, UNDEF_ALL_8x16), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_PolynomialMulAdd16x8, UNDEF_ALL_16x8), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_PolynomialMulAdd32x4, UNDEF_ALL_32x4), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_PolynomialMulAdd64x2, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_CipherV128, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_CipherLV128, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_CipherSV128, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_NCipherV128, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_NCipherLV128, UNDEF_ALL_64x2), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_SHA512, UNDEF_SOME), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_SHA256, UNDEF_SOME), .ppc64 = 1, .ppc32 = 1 },
+ { DEFOP(Iop_PwBitMtxXpose64x2, UNDEF_64x2_TRANSPOSE), .ppc64 = 1, .ppc32 = 1 },
};
/* Force compile time failure in case libvex_ir.h::IROp was updated
irop_t *
get_irop(IROp op)
{
+ int rc;
unsigned i;
for (i = 0; i < sizeof irops / sizeof *irops; ++i) {
case Iop_F64toI64U:
case Iop_F128toI32U:
case Iop_F128toI64U: {
- int rc;
/* These IROps require the floating point extension facility */
rc = system(S390X_FEATURES " s390x-fpext");
// s390x_features returns 1 if feature does not exist
case Iop_I64UtoF64:
case Iop_I64UtoF32:
case Iop_I64StoD64: {
- int rc;
- /* IROps require a processor that supports ISA 2.06 or newer */
+ /* IROps require a processor that supports ISA 2.06 (Power 7) or newer */
rc = system(MIN_POWER_ISA " 2.06 ");
rc /= 256;
/* MIN_POWER_ISA returns 0 if underlying HW supports the
* the specified ISA. Returns 2 on error.
*/
if (rc == 1) return NULL;
+ if (rc > 2) {
+ panic(" ERROR, min_power_isa() return code is invalid.\n");
+ }
+ }
+ case Iop_PwBitMtxXpose64x2:
+ case Iop_Clz64x2:
+ case Iop_BCDAdd:
+ case Iop_BCDSub:
+ case Iop_PolynomialMulAdd8x16:
+ case Iop_PolynomialMulAdd16x8:
+ case Iop_PolynomialMulAdd32x4:
+ case Iop_PolynomialMulAdd64x2:
+ case Iop_CipherV128:
+ case Iop_CipherLV128:
+ case Iop_CipherSV128:
+ case Iop_NCipherV128:
+ case Iop_NCipherLV128:
+ case Iop_SHA512:
+ case Iop_SHA256:
+ case Iop_MullEven8Ux16:
+ case Iop_MullEven16Ux8:
+ case Iop_MullEven32Ux4:
+ case Iop_MullEven8Sx16:
+ case Iop_MullEven16Sx8:
+ case Iop_MullEven32Sx4:
+ case Iop_Max64Sx2:
+ case Iop_Max64Ux2:
+ case Iop_Min64Sx2:
+ case Iop_Min64Ux2:
+ case Iop_CmpGT64Ux2:
+ case Iop_Rol64x2:
+ case Iop_QNarrowBin64Sto32Sx4:
+ case Iop_QNarrowBin64Uto32Ux4:
+ case Iop_NarrowBin64to32x4: {
+ /* IROps require a processor that supports ISA 2.07 (Power 8) or newer */
+ rc = system(MIN_POWER_ISA " 2.07 ");
+ rc /= 256;
+ /* MIN_POWER_ISA returns 0 if underlying HW supports the
+ * specified ISA or newer. Returns 1 if the HW does not support
+ * the specified ISA. Returns 2 on error.
+ */
+ if (rc == 1) return NULL;
if (rc > 2) {
panic(" ERROR, min_power_isa() return code is invalid.\n");
}
fixup_irops(void)
{
#ifdef __powerpc__
- get_irop(Iop_ShlD64)->shift_amount_is_immediate = 1;
- get_irop(Iop_ShrD64)->shift_amount_is_immediate = 1;
- get_irop(Iop_ShlD128)->shift_amount_is_immediate = 1;
- get_irop(Iop_ShrD128)->shift_amount_is_immediate = 1;
+ irop_t* tmp;
+
+ /* Iops with immediate shift value */
+ tmp = get_irop(Iop_ShlD64);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_ShrD64);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_ShlD128);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_ShrD128);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ /* Iops with immediate value that controls PPC instruction behavior */
+ tmp = get_irop(Iop_SHA256);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_SHA512);
+ if (tmp) {
+ tmp->immediate_index = 2;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_BCDAdd);
+ if (tmp) {
+ tmp->immediate_index = 3;
+ tmp->immediate_type = Ity_I8;
+ }
+
+ tmp = get_irop(Iop_BCDSub);
+ if (tmp) {
+ tmp->immediate_index = 3;
+ tmp->immediate_type = Ity_I8;
+ }
#endif
}
opnd_t *opnds = data->opnds;
int tests_done = 0;
+ /* Immediate operands are currently not supported here */
+ assert(op->immediate_index == 0);
+
/* For each operand, set a single bit to undefined and observe how
that propagates to the output. Do this for all bits in each
operand. */
opnd3->vbits);
break;
+ case UNDEF_SOME:
+ /* The result of the Iop_BCDAdd and the Iop_BCDSub has some result
+ * vbits set. Not sure how the vbit propagation works on these Iops.
+ * for now, just make sure there are some vbits set in the result.
+ *
+ * The Iop_BCDAdd and Iop_BCDSub iops have one immediate value in the
+ * third operand.
+ *
+ * TODO, figure out details of vbit propagation for these Iops.
+ */
+ expected_vbits.num_bits = result->vbits.num_bits;
+
+ if ((result->vbits.bits.u128[0] != 0) ||
+ (result->vbits.bits.u128[1] != 0)) {
+ expected_vbits.bits.u128[0] = result->vbits.bits.u128[0];
+ expected_vbits.bits.u128[1] = result->vbits.bits.u128[1];
+
+ } else {
+ /* The input had at least one vbit set but the result doesn't have any
+ * bit set. Set them all so we will trigger the error on the call
+ * to complain().
+ */
+ expected_vbits.bits.u128[0] = ~0x0ULL;
+ expected_vbits.bits.u128[1] = ~0x0ULL;
+ }
+
+ break;
+
default:
panic(__func__);
}
expected_vbits = zextend_vbits(opnd->vbits, num_bits);
break;
+ case UNDEF_ALL_64x2:
+ assert(num_bits == 128);
+ expected_vbits = undefined_vbits_BxE(64, 2, opnd->vbits);
+ break;
+
+ case UNDEF_ALL_32x4:
+ assert(num_bits == 128);
+ expected_vbits = undefined_vbits_BxE(32, 4, opnd->vbits);
+ break;
+
+ case UNDEF_ALL_16x8:
+ assert(num_bits == 128);
+ expected_vbits = undefined_vbits_BxE(16, 8, opnd->vbits);
+ break;
+
+ case UNDEF_ALL_8x16:
+ assert(num_bits == 128);
+ expected_vbits = undefined_vbits_BxE(8, 16, opnd->vbits);
+ break;
+
+ case UNDEF_64x2_TRANSPOSE:
+ assert(num_bits == 128);
+ expected_vbits = undefined_vbits_64x2_transpose(opnd->vbits);
+ break;
+
default:
panic(__func__);
}
unsigned num_input_bits, bitpos;
int tests_done = 0;
+ /* Immediate operands are currently not supported here */
+ assert(op->immediate_index == 0);
+
num_input_bits = bitsof_irtype(data->opnds[0].type);
for (bitpos = 0; bitpos < num_input_bits; ++bitpos) {
cb.num_operands = get_num_operands(op->op);
- cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
+ cb.immediate_index = op->immediate_index;
+ cb.immediate_type = op->immediate_type;
return cb;
}
return new;
}
+/* The following routines named undefined_vbits_BxE() return a 128-bit
+ * vector with E elements each of size bits. If any of the bits in an
+ * element is undefined, then return a value where all bits in that
+ * element are undefined.
+ */
+vbits_t
+undefined_vbits_BxE(unsigned int bits, unsigned int elements, vbits_t v)
+{
+ vbits_t new = { .num_bits = v.num_bits };
+ uint64_t mask = ~0ull >> (64 - bits);
+ int i, j;
+
+ assert ((elements % 2) == 0);
+ assert (bits <= 64);
+
+ for (i = 0; i<2; i++) {
+ new.bits.u128[i] = 0ull;
+
+ for (j = 0; j<elements/2; j++) {
+ if ((v.bits.u128[i] & (mask << (j*bits))) != 0)
+ new.bits.u128[i] |= (mask << (j*bits));
+ }
+ }
+ return new;
+}
+
+/* The following routines named undefined_vbits_BxE_rotate() return a 128-bit
+ * vector with E elements each of size bits. The bits in v are rotated
+ * left by the amounts in the corresponding element of val. Specified rotate
+ * amount field is assumed to be at most 8-bits wide.
+ */
+vbits_t
+undefined_vbits_BxE_rotate(unsigned int bits, unsigned int elements,
+ vbits_t v, value_t val)
+{
+ vbits_t new = { .num_bits = v.num_bits };
+ uint64_t mask = ~0ull >> (64 - bits);
+ uint64_t const shift_mask = 0xFF;
+ uint64_t element;
+ int i, j;
+ signed char shift;
+ assert ((elements % 2) == 0);
+ assert (bits <= 64);
+
+ for (i = 0; i<2; i++) {
+ new.bits.u128[i] = 0ull;
+
+ for (j = 0; j<elements/2; j++) {
+ element = (v.bits.u128[i] >> (j*bits)) & mask;
+ shift = (int)((val.u128[i] >> (j*bits)) & shift_mask);
+
+ if (shift < 0) {
+ /* right shift */
+ new.bits.u128[i] = element >> -shift;
+
+ /* OR in the bits shifted out into the top of the element */
+ new.bits.u128[i] |= element << (bits + shift);
+ } else {
+ /* left shift */
+ /* upper bits from shift */
+ new.bits.u128[i] = element << shift;
+
+ /* OR in the bits shifted out into the bottom of the element */
+ new.bits.u128[i] |= element >> (bits - shift);
+ }
+ }
+ }
+ return new;
+}
+
+/* Only the even elements of the input are used by the Iop*/
+vbits_t
+undefined_vbits_128_even_element(unsigned int bits, unsigned int elements,
+ vbits_t v)
+{
+ int i;
+ uint64_t mask;
+ unsigned int const element_width = 128/elements;
+ vbits_t new = { .num_bits = v.num_bits };
+
+ assert ((elements % 2) == 0);
+ assert (bits <= 64);
+
+ /* Create a 128-bit mask with the bits in the even numbered
+ * elements are all ones.
+ */
+ mask = ~0ull >> (64 - bits);
+
+ for (i = 2; i < elements/2; i=i+2) {
+ mask |= mask << (i * element_width);
+ }
+
+ new.bits.u128[0] = mask & v.bits.u128[0];
+ new.bits.u128[1] = mask & v.bits.u128[1];
+
+ return new;
+}
+
+/* Concatenate bit i from each byte j. Place concatenated 8 bit value into
+ * byte i of the result. Do for all i from 0 to 7 and j from 0 to 7 of each
+ * 64-bit element.
+ */
+vbits_t
+undefined_vbits_64x2_transpose(vbits_t v)
+{
+ vbits_t new = { .num_bits = v.num_bits };
+ unsigned int bit, byte, element;
+ uint64_t value, new_value, select_bit;
+
+ for (element = 0; element < 2; element++) {
+ value = v.bits.u128[element];
+ new_value = 0;
+ for (byte = 0; byte < 8; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ select_bit = 1ULL & (value >> (bit + 8*byte));
+ new_value |= select_bit << (bit*8 + byte);
+ }
+ }
+ new.bits.u128[element] = new_value;
+ }
+ return new;
+}
+
+/* The routine takes a 256-bit vector value stored across the two 128-bit
+ * source operands src1 and src2. The size of each element in the input is
+ * src_num_bits. The elements are narrowed to result_num_bits and packed
+ * into the result. If saturate is True, then the all the result bits are
+ * set to 1 if the source element can not be represented in result_num_bits.
+ */
+vbits_t
+undefined_vbits_Narrow256_AtoB(unsigned int src_num_bits,
+ unsigned int result_num_bits,
+ vbits_t src1_v, value_t src1_value,
+ vbits_t src2_v, value_t src2_value,
+ bool saturate)
+{
+
+ vbits_t new = { .num_bits = src1_v.num_bits };
+ unsigned int i;
+ uint64_t vbits, new_value;
+ uint64_t const src_mask = ~0x0ULL >> (64 - src_num_bits);
+ uint64_t const result_mask = ~0x0ULL >> (64 - result_num_bits);
+ unsigned int num_elements_per_64_bits = src_num_bits/64;
+ unsigned int shift;
+
+ /*
+ * NOTE: POWER PPC
+ * the saturated value is 0xFFFF for the vbit is in one of the lower
+ * 32-bits of the source. The saturated result is 0xFFFF0000 if the
+ * vbit is in the upper 32-bits of the source. Not sure what
+ * the saturated result is in general for a B-bit result.
+ *
+ * ONLY TESTED FOR 64 bit input, 32 bit result
+ */
+ uint64_t const saturated_result = 0xFFFFULL;
+
+ /* Source elements are split between the two source operands */
+
+ assert(src_num_bits <= 64);
+ assert(result_num_bits < 64);
+ assert(result_num_bits < src_num_bits);
+
+ /* Narrow the elements from src1 to the upper 64-bits of result.
+ * Do each of the 64 bit values that make up a u128
+ */
+ new_value = 0;
+ for (i = 0; i < num_elements_per_64_bits; i++) {
+ vbits = src1_v.bits.u128[0] >> (i * src_num_bits);
+ vbits &= src_mask;
+
+ shift = result_num_bits * i;
+ if (vbits) {
+ if (saturate) {
+ /* Value will not fit in B-bits, saturate the result as needed. */
+ if (vbits >> (src_num_bits/2))
+ /* vbit is upper half of the source */
+ new_value |= saturated_result << ( shift + result_num_bits/2);
+ else
+ new_value |= saturated_result << shift;
+ } else {
+ new_value |= (vbits & result_mask) << shift;
+ }
+ }
+ }
+
+ for (i = 0; i < num_elements_per_64_bits; i++) {
+ vbits = src1_v.bits.u128[1] >> (i * src_num_bits);
+ vbits &= src_mask;
+
+ shift = result_num_bits * i + (num_elements_per_64_bits
+ * result_num_bits);
+ if (vbits) {
+ if (saturate) {
+ /* Value will not fit in result_num_bits, saturate the result
+ * as needed.
+ */
+ if (vbits >> (src_num_bits/2))
+ /* vbit is upper half of the source */
+ new_value |= saturated_result << (shift + result_num_bits/2);
+
+ else
+ new_value |= saturated_result << shift;
+
+ } else {
+ new_value |= (vbits & result_mask) << shift;
+ }
+ }
+ }
+ if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ new.bits.u128[1] = new_value;
+ else
+ /* Big endian, swap the upper and lower 32-bits of new_value */
+ new.bits.u128[0] = (new_value << 32) | (new_value >> 32);
+
+ new_value = 0;
+ /* Narrow the elements from src2 to the lower 64-bits of result.
+ * Do each of the 64 bit values that make up a u128
+ */
+ for (i = 0; i < num_elements_per_64_bits; i++) {
+ vbits = src2_v.bits.u128[0] >> (i * src_num_bits);
+ vbits &= src_mask;
+
+ shift = result_num_bits * i;
+ if (vbits) {
+ if (saturate) {
+ /* Value will not fit in result, saturate the result as needed. */
+ if (vbits >> (src_num_bits/2))
+ /* vbit is upper half of the source */
+ new_value |= saturated_result << (shift + result_num_bits/2);
+ else
+ new_value |= saturated_result << shift;
+ } else {
+ new_value |= (vbits & result_mask) << shift;
+ }
+ }
+ }
+
+ for (i = 0; i < num_elements_per_64_bits; i++) {
+ vbits = src2_v.bits.u128[1] >> (i * src_num_bits);
+ vbits &= src_mask;
+
+ if (vbits) {
+ if (saturate) {
+ /* Value will not fit in result_num_bits, saturate the result
+ * as needed.
+ */
+ if (vbits >> (src_num_bits/2))
+ /* vbit is upper half of the source */
+ new_value |= saturated_result << (result_num_bits * i
+ + result_num_bits/2
+ + (num_elements_per_64_bits
+ * result_num_bits));
+ else
+ new_value |= saturated_result << (result_num_bits * i
+ + (num_elements_per_64_bits
+ * result_num_bits));
+
+ } else {
+ new_value |= (vbits & result_mask) << (result_num_bits * i
+ + (num_elements_per_64_bits
+ * result_num_bits));
+ }
+ }
+ }
+ if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ new.bits.u128[0] = new_value;
+ else
+ /* Big endian, swap the upper and lower 32-bits of new_value */
+ new.bits.u128[1] = (new_value << 32) | (new_value >> 32);
+
+ return new;
+}
/* Return a value where all bits are set to defined. */
vbits_t
#include <stdint.h>
#include <stdio.h>
+#include <stdbool.h>
typedef uint64_t uint128_t[2];
typedef uint64_t uint256_t[4];
void print_vbits(FILE *, vbits_t);
vbits_t undefined_vbits(unsigned num_bits);
+vbits_t undefined_vbits_BxE(unsigned int bits, unsigned int elements,
+ vbits_t v);
+vbits_t undefined_vbits_BxE_rotate(unsigned int bits, unsigned int elements,
+ vbits_t vbits,
+ value_t value);
+vbits_t undefined_vbits_128_even_element(unsigned int bits,
+ unsigned int elements, vbits_t v);
+vbits_t undefined_vbits_64x2_transpose(vbits_t v);
+vbits_t undefined_vbits_Narrow256_AtoB(unsigned int src_num_bits,
+ unsigned int result_num_bits,
+ vbits_t src1_v, value_t src1_value,
+ vbits_t src2_v, value_t src2_value,
+ bool sataurate);
vbits_t defined_vbits(unsigned num_bits);
int equal_vbits(vbits_t, vbits_t);
vbits_t truncate_vbits(vbits_t, unsigned num_bits);
UNDEF_ORD, // Iop_CmpORD compare
+ /* For each of the following UNDEF_ALL_BxE, E is the number of
+ * elements and B is the number of bits in the element.
+ *
+ * If any bits in one of the E elements is not defined, then the
+ * return value has all bits in the corresponding element set to 1.
+ */
+ UNDEF_ALL_64x2, // 128-bit vector, two 64-bit elements
+ UNDEF_ALL_32x4, // 128-bit vector, four 32-bit elements
+ UNDEF_ALL_16x8, // 128-bit vector, eight 16-bit elements
+ UNDEF_ALL_8x16, // 128-bit vector, sixteen 8-bit elements
+
+ /* For each of the following UNDEF_ALL_BxE_EVEN, E is the number of
+ * elements and B is the number of bits in the element. Elements are
+ * numbered from right to left starting with element number 0.
+ *
+ * If any bits in one of the even numbered elements is not defined, then
+ * the return value has all bits in the corresponding element set to 1.
+ * The bits in the odd numbered elements are not checked
+ */
+ UNDEF_ALL_32x4_EVEN, // 128-bit vector, four 32-bit elements
+ UNDEF_ALL_16x8_EVEN, // 128-bit vector, eight 16-bit elements
+ UNDEF_ALL_8x16_EVEN, // 128-bit vector, sixteen 8-bit elements
+
+ /* For each of the following UNDEF_BxE_TRANSPOSE, E is the number of
+ * elements and B is the number of bits in the element.
+ *
+ * Concatenate bit i from each byte j. Place concatenated 8 bit value
+ * into byte i of the result. Do for each bit i from 0 to 7 and
+ * byte j from 0 to 7 of each 64-bit element.
+ */
+ UNDEF_64x2_TRANSPOSE,
+
+ /* For each of the following UNDEF_BxE_ROTATE, E is the number of
+ * elements and B is the number of bits in the element.
+ *
+ * The result is the undefined bits in each element rotated by the
+ * specified amount. Bits rotated out of the element are discarded.
+ * No additional bits are set to undefined.
+ */
+ UNDEF_64x2_ROTATE, /* 128-bit vector, two 64-bit elements, rotate
+ * elements left.
+ */
+ UNDEF_32x4_ROTATE, /* 128-bit vector, four 32-bit elements, rotate
+ * elements left.
+ */
+ UNDEF_16x8_ROTATE, /* 128-bit vector, eight 16-bit elements, rotate
+ * elements left.
+ */
+ UNDEF_8x16_ROTATE, /* 128-bit vector, sixteen 8-bit elements, rotate
+ * elements left.
+ */
+
+ /* If the input had some vbits set, the result will have one or more
+ * vbits set. Minimal test when the vbit propagation can not be easily
+ * calculated.
+ */
+ UNDEF_SOME,
+
+ /* For UNDEF_NARROW256_AtoB, narrow the elements of size A-bits in
+ * the 256-bit source (stored in two 128-bit values) to a 128-bit
+ * result with elements of size B-bits.
+ *
+ * If the source element will fit into the corresponding destination
+ * element, then only the undefined bits in the source element are
+ * undefined in the corresponding bit position of the destination element.
+ *
+ * If the source element will not fit into the destination element, then
+ * only the lower B undefined bits of the source element will be
+ * undefined in the corresponding result element unless the saturate
+ * flag is true. If the saturate flag is true and the element in the
+ * source will not fit into the corresponding destination element, then
+ * all of the bits in the corresponding destination element are set to one.
+ */
+ UNDEF_NARROW256_AtoB,
+
// For IROps I don't know anything about
UNDEF_UNKNOWN
} undef_t;
IROp op;
const char *name;
undef_t undef_kind;
- int shift_amount_is_immediate;
+ /* The following two members describe if this operand has immediate
+ * operands. There are a few restrictions:
+ * (1) An operator can have at most one immediate operand.
+ * (2) If there is an immediate operand, it is the right-most operand.
+ * An immediate_index of 0 means there is no immediate operand.
+ */
+ unsigned immediate_index;
+ unsigned immediate_type;
+
// Indicate whether IROp can be tested on a particular architecture
unsigned s390x : 1;
unsigned amd64 : 1;