From: Julian Seward Date: Sat, 15 Nov 2014 16:07:14 +0000 (+0000) Subject: Implement fcsel d_d, s_s. Fixes #340856. X-Git-Tag: svn/VALGRIND_3_11_0^2~160 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3dfab124575a38bda4e15896d732ae5593399858;p=thirdparty%2Fvalgrind.git Implement fcsel d_d, s_s. Fixes #340856. git-svn-id: svn://svn.valgrind.org/vex/trunk@2991 --- diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c index 1426d003cd..eb13f383fd 100644 --- a/VEX/priv/guest_arm64_toIR.c +++ b/VEX/priv/guest_arm64_toIR.c @@ -11844,7 +11844,40 @@ Bool dis_AdvSIMD_fp_conditional_compare(/*MB_OUT*/DisResult* dres, UInt insn) 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 } diff --git a/VEX/priv/host_arm64_defs.c b/VEX/priv/host_arm64_defs.c index 62db9921bb..e18c5a5760 100644 --- a/VEX/priv/host_arm64_defs.c +++ b/VEX/priv/host_arm64_defs.c @@ -1112,6 +1112,17 @@ ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) { 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; @@ -1646,6 +1657,18 @@ void ppARM64Instr ( const ARM64Instr* i ) { 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, "); @@ -2028,6 +2051,11 @@ void getRegUsage_ARM64Instr ( HRegUsage* u, const ARM64Instr* i, Bool mode64 ) 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); @@ -2256,6 +2284,11 @@ void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 ) 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; @@ -3958,6 +3991,21 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc, *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); diff --git a/VEX/priv/host_arm64_defs.h b/VEX/priv/host_arm64_defs.h index 9420eb650b..05615ea8ca 100644 --- a/VEX/priv/host_arm64_defs.h +++ b/VEX/priv/host_arm64_defs.h @@ -491,6 +491,7 @@ typedef ARM64in_VBinS, ARM64in_VCmpD, ARM64in_VCmpS, + ARM64in_VFCSel, ARM64in_FPCR, ARM64in_FPSR, /* ARM64in_V*V: vector ops on vector registers */ @@ -743,6 +744,15 @@ typedef 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; @@ -889,6 +899,8 @@ extern ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op, HReg, HReg, HReg ); 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 ); diff --git a/VEX/priv/host_arm64_isel.c b/VEX/priv/host_arm64_isel.c index f11e0b358f..f0879f6a8e 100644 --- a/VEX/priv/host_arm64_isel.c +++ b/VEX/priv/host_arm64_isel.c @@ -3067,6 +3067,17 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) } } + 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"); } @@ -3222,6 +3233,17 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) } } + 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"); }