static
Bool dis_AdvSIMD_fp_conditional_select(/*MB_OUT*/DisResult* dres, UInt insn)
{
+ /* 31 23 21 20 15 11 9 5
+ 000 11110 ty 1 m cond 11 n d
+ The first 3 bits are really "M 0 S", but M and S are always zero.
+ Decode fields: ty
+ */
# define INSN(_bMax,_bMin) SLICE_UInt(insn, (_bMax), (_bMin))
+ if (INSN(31,24) != BITS8(0,0,0,1,1,1,1,0) || INSN(21,21) != 1
+ || INSN(11,10) != BITS2(1,1)) {
+ return False;
+ }
+ UInt ty = INSN(23,22);
+ UInt mm = INSN(20,16);
+ UInt cond = INSN(15,12);
+ UInt nn = INSN(9,5);
+ UInt dd = INSN(4,0);
+ if (ty <= X01) {
+ /* -------- 00: FCSEL s_s -------- */
+ /* -------- 00: FCSEL d_d -------- */
+ IRType ity = ty == X01 ? Ity_F64 : Ity_F32;
+ IRTemp srcT = newTemp(ity);
+ IRTemp srcF = newTemp(ity);
+ IRTemp res = newTemp(ity);
+ assign(srcT, getQRegLO(nn, ity));
+ assign(srcF, getQRegLO(mm, ity));
+ assign(res, IRExpr_ITE(
+ unop(Iop_64to1, mk_arm64g_calculate_condition(cond)),
+ mkexpr(srcT), mkexpr(srcF)));
+ putQReg128(dd, mkV128(0x0000));
+ putQRegLO(dd, mkexpr(res));
+ DIP("fcsel %s, %s, %s, %s\n",
+ nameQRegLO(dd, ity), nameQRegLO(nn, ity), nameQRegLO(mm, ity),
+ nameCC(cond));
+ return True;
+ }
return False;
# undef INSN
}
i->ARM64in.VCmpS.argR = argR;
return i;
}
+ARM64Instr* ARM64Instr_VFCSel ( HReg dst, HReg argL, HReg argR,
+ ARM64CondCode cond, Bool isD ) {
+ ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
+ i->tag = ARM64in_VFCSel;
+ i->ARM64in.VFCSel.dst = dst;
+ i->ARM64in.VFCSel.argL = argL;
+ i->ARM64in.VFCSel.argR = argR;
+ i->ARM64in.VFCSel.cond = cond;
+ i->ARM64in.VFCSel.isD = isD;
+ return i;
+}
ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
i->tag = ARM64in_FPCR;
vex_printf(", ");
ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
return;
+ case ARM64in_VFCSel: {
+ void (*ppHRegARM64fp)(HReg)
+ = (i->ARM64in.VFCSel.isD ? ppHRegARM64 : ppHRegARM64asSreg);
+ vex_printf("fcsel ");
+ ppHRegARM64fp(i->ARM64in.VFCSel.dst);
+ vex_printf(", ");
+ ppHRegARM64fp(i->ARM64in.VFCSel.argL);
+ vex_printf(", ");
+ ppHRegARM64fp(i->ARM64in.VFCSel.argR);
+ vex_printf(", %s", showARM64CondCode(i->ARM64in.VFCSel.cond));
+ return;
+ }
case ARM64in_FPCR:
if (i->ARM64in.FPCR.toFPCR) {
vex_printf("msr fpcr, ");
addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
return;
+ case ARM64in_VFCSel:
+ addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argL);
+ addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argR);
+ addHRegUse(u, HRmWrite, i->ARM64in.VFCSel.dst);
+ return;
case ARM64in_FPCR:
if (i->ARM64in.FPCR.toFPCR)
addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
i->ARM64in.VCmpS.argL = lookupHRegRemap(m, i->ARM64in.VCmpS.argL);
i->ARM64in.VCmpS.argR = lookupHRegRemap(m, i->ARM64in.VCmpS.argR);
return;
+ case ARM64in_VFCSel:
+ i->ARM64in.VFCSel.argL = lookupHRegRemap(m, i->ARM64in.VFCSel.argL);
+ i->ARM64in.VFCSel.argR = lookupHRegRemap(m, i->ARM64in.VFCSel.argR);
+ i->ARM64in.VFCSel.dst = lookupHRegRemap(m, i->ARM64in.VFCSel.dst);
+ return;
case ARM64in_FPCR:
i->ARM64in.FPCR.iReg = lookupHRegRemap(m, i->ARM64in.FPCR.iReg);
return;
*p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
goto done;
}
+ case ARM64in_VFCSel: {
+ /* 31 23 21 20 15 11 9 5
+ 000 11110 00 1 m cond 11 n d FCSEL Sd,Sn,Sm,cond
+ 000 11110 01 1 m cond 11 n d FCSEL Dd,Dn,Dm,cond
+ */
+ Bool isD = i->ARM64in.VFCSel.isD;
+ UInt dd = dregNo(i->ARM64in.VFCSel.dst);
+ UInt nn = dregNo(i->ARM64in.VFCSel.argL);
+ UInt mm = dregNo(i->ARM64in.VFCSel.argR);
+ UInt cond = (UInt)i->ARM64in.VFCSel.cond;
+ vassert(cond < 16);
+ *p++ = X_3_8_5_6_5_5(X000, isD ? X11110011 : X11110001,
+ mm, (cond << 2) | X000011, nn, dd);
+ goto done;
+ }
case ARM64in_FPCR: {
Bool toFPCR = i->ARM64in.FPCR.toFPCR;
UInt iReg = iregNo(i->ARM64in.FPCR.iReg);
ARM64in_VBinS,
ARM64in_VCmpD,
ARM64in_VCmpS,
+ ARM64in_VFCSel,
ARM64in_FPCR,
ARM64in_FPSR,
/* ARM64in_V*V: vector ops on vector registers */
HReg argL;
HReg argR;
} VCmpS;
+ /* 32- or 64-bit FP conditional select */
+ struct {
+ HReg dst;
+ HReg argL;
+ HReg argR;
+ ARM64CondCode cond;
+ Bool isD;
+ }
+ VFCSel;
/* Move a 32-bit value to/from the FPCR */
struct {
Bool toFPCR;
extern ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op, HReg, HReg, HReg );
extern ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR );
extern ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR );
+extern ARM64Instr* ARM64Instr_VFCSel ( HReg dst, HReg argL, HReg argR,
+ ARM64CondCode cond, Bool isD );
extern ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg );
extern ARM64Instr* ARM64Instr_FPSR ( Bool toFPSR, HReg iReg );
extern ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op, HReg, HReg, HReg );
}
}
+ if (e->tag == Iex_ITE) {
+ /* ITE(ccexpr, iftrue, iffalse) */
+ ARM64CondCode cc;
+ HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue);
+ HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse);
+ HReg dst = newVRegD(env);
+ cc = iselCondCode(env, e->Iex.ITE.cond);
+ addInstr(env, ARM64Instr_VFCSel(dst, r1, r0, cc, True/*64-bit*/));
+ return dst;
+ }
+
ppIRExpr(e);
vpanic("iselDblExpr_wrk");
}
}
}
+ if (e->tag == Iex_ITE) {
+ /* ITE(ccexpr, iftrue, iffalse) */
+ ARM64CondCode cc;
+ HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
+ HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
+ HReg dst = newVRegD(env);
+ cc = iselCondCode(env, e->Iex.ITE.cond);
+ addInstr(env, ARM64Instr_VFCSel(dst, r1, r0, cc, False/*!64-bit*/));
+ return dst;
+ }
+
ppIRExpr(e);
vpanic("iselFltExpr_wrk");
}