return emit_RRF6(p, 0xb9650000, r1, r2, r3);
}
+static UChar *
+s390_emit_NNRK(UChar *p, UChar r1, UChar r2, UChar r3)
+{
+ return emit_RRF6(p, 0xb9740000, r1, r2, r3);
+}
+
+static UChar *
+s390_emit_NNGRK(UChar *p, UChar r1, UChar r2, UChar r3)
+{
+ return emit_RRF6(p, 0xb9640000, r1, r2, r3);
+}
+
+static UChar *
+s390_emit_NORK(UChar *p, UChar r1, UChar r2, UChar r3)
+{
+ return emit_RRF6(p, 0xb9760000, r1, r2, r3);
+}
+
+static UChar *
+s390_emit_NOGRK(UChar *p, UChar r1, UChar r2, UChar r3)
+{
+ return emit_RRF6(p, 0xb9660000, r1, r2, r3);
+}
+
/* Provide a symbolic name for register "R0" */
#define R0 0
switch (insn->variant.alu3.tag) {
case S390_ALU3_ANDC: op = "v-andc"; break;
case S390_ALU3_ORC: op = "v-orc"; break;
+ case S390_ALU3_NAND: op = "v-nand"; break;
+ case S390_ALU3_NOR: op = "v-nor"; break;
default: goto fail;
}
s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.alu3.dst,
case S390_ALU3_ORC:
return insn->size == 4 ? s390_emit_OCRK(buf, dst, op1, op2)
: s390_emit_OCGRK(buf, dst, op1, op2);
+ case S390_ALU3_NAND:
+ return insn->size == 4 ? s390_emit_NNRK(buf, dst, op1, op2)
+ : s390_emit_NNGRK(buf, dst, op1, op2);
+ case S390_ALU3_NOR:
+ return insn->size == 4 ? s390_emit_NORK(buf, dst, op1, op2)
+ : s390_emit_NOGRK(buf, dst, op1, op2);
default:
goto fail;
}
return dst;
}
- /* Regular processing */
-
if (unop == Iop_128to64) {
HReg dst_hi, dst_lo;
return dst;
}
+ /* NAND or NOR */
+ if ((env->hwcaps & VEX_HWCAPS_S390X_MI3) && is_IRExpr_Not(expr) &&
+ arg->tag == Iex_Binop) {
+ s390_alu3_t bitop;
+
+ switch (binop) {
+ case Iop_And8:
+ case Iop_And16:
+ case Iop_And32:
+ case Iop_And64:
+ bitop = S390_ALU3_NAND;
+ goto do_nand_nor;
+ case Iop_Or8:
+ case Iop_Or16:
+ case Iop_Or32:
+ case Iop_Or64:
+ bitop = S390_ALU3_NOR;
+ do_nand_nor: {
+ HReg h2;
+ dst = newVRegI(env);
+ h1 = s390_isel_int_expr(env, arg->Iex.Binop.arg1);
+ h2 = s390_isel_int_expr(env, arg->Iex.Binop.arg2);
+ addInstr(env,
+ s390_insn_alu3(size <= 4 ? 4 : 8, bitop, dst, h1, h2));
+ return dst;
+ }
+ default:;
+ }
+ }
+
+ /* Regular processing */
+
dst = newVRegI(env); /* Result goes into a new register */
opnd = s390_isel_int_expr_RMI(env, arg); /* Process the operand */
case Iop_Not16:
case Iop_Not32:
case Iop_Not64:
- /* XOR with ffff... */
- mask.variant.imm = ~(ULong)0;
- addInstr(env, s390_opnd_copy(size, dst, opnd));
- insn = s390_insn_alu(size, S390_ALU_XOR, dst, mask);
+ if ((env->hwcaps & VEX_HWCAPS_S390X_MI3) &&
+ opnd.tag == S390_OPND_REG) {
+ insn = s390_insn_alu3(size <= 4 ? 4 : 8, S390_ALU3_NOR, dst,
+ opnd.variant.reg, opnd.variant.reg);
+ } else {
+ /* XOR with ffff... */
+ addInstr(env, s390_opnd_copy(size, dst, opnd));
+ mask.variant.imm = ~(ULong)0;
+ insn = s390_insn_alu(size, S390_ALU_XOR, dst, mask);
+ }
break;
case Iop_Left8: