} else {
vassert(op == BITS3(1,0,0) || op == BITS3(1,0,1));
switch (rm) {
- case BITS2(0,0): ch = 'a'; irrm = Irrm_NEAREST; break;
+ case BITS2(0,0): ch = 'a'; irrm = Irrm_NEAREST_TIE_AWAY_0; break;
default: vassert(0);
}
}
IROp iop = iops[ix];
// A bit of ATCery: bounce all cases we haven't seen an example of.
if (/* F32toI32S */
- (iop == Iop_F32toI32S && irrm == Irrm_ZERO) /* FCVTZS Wd,Sn */
- || (iop == Iop_F32toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Sn */
- || (iop == Iop_F32toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Sn */
- || (iop == Iop_F32toI32S && irrm == Irrm_NEAREST)/* FCVT{A,N}S W,S */
+ (iop == Iop_F32toI32S && irrm == Irrm_ZERO) /* FCVTZS Wd,Sn */
+ || (iop == Iop_F32toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Sn */
+ || (iop == Iop_F32toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Sn */
+ || (iop == Iop_F32toI32S && irrm == Irrm_NEAREST) /* FCVTNS W,S */
+ || (iop == Iop_F32toI32S && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAS W,S */
/* F32toI32U */
- || (iop == Iop_F32toI32U && irrm == Irrm_ZERO) /* FCVTZU Wd,Sn */
- || (iop == Iop_F32toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Sn */
- || (iop == Iop_F32toI32U && irrm == Irrm_PosINF) /* FCVTPU Wd,Sn */
- || (iop == Iop_F32toI32U && irrm == Irrm_NEAREST)/* FCVT{A,N}U W,S */
+ || (iop == Iop_F32toI32U && irrm == Irrm_ZERO) /* FCVTZU Wd,Sn */
+ || (iop == Iop_F32toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Sn */
+ || (iop == Iop_F32toI32U && irrm == Irrm_PosINF) /* FCVTPU Wd,Sn */
+ || (iop == Iop_F32toI32U && irrm == Irrm_NEAREST) /* FCVTNU W,S */
+ || (iop == Iop_F32toI32U && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAU W,S */
/* F32toI64S */
- || (iop == Iop_F32toI64S && irrm == Irrm_ZERO) /* FCVTZS Xd,Sn */
- || (iop == Iop_F32toI64S && irrm == Irrm_NegINF) /* FCVTMS Xd,Sn */
- || (iop == Iop_F32toI64S && irrm == Irrm_PosINF) /* FCVTPS Xd,Sn */
- || (iop == Iop_F32toI64S && irrm == Irrm_NEAREST)/* FCVT{A,N}S X,S */
+ || (iop == Iop_F32toI64S && irrm == Irrm_ZERO) /* FCVTZS Xd,Sn */
+ || (iop == Iop_F32toI64S && irrm == Irrm_NegINF) /* FCVTMS Xd,Sn */
+ || (iop == Iop_F32toI64S && irrm == Irrm_PosINF) /* FCVTPS Xd,Sn */
+ || (iop == Iop_F32toI64S && irrm == Irrm_NEAREST) /* FCVTNS X,S */
+ || (iop == Iop_F32toI64S && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAS X,S */
/* F32toI64U */
- || (iop == Iop_F32toI64U && irrm == Irrm_ZERO) /* FCVTZU Xd,Sn */
- || (iop == Iop_F32toI64U && irrm == Irrm_NegINF) /* FCVTMU Xd,Sn */
- || (iop == Iop_F32toI64U && irrm == Irrm_PosINF) /* FCVTPU Xd,Sn */
- || (iop == Iop_F32toI64U && irrm == Irrm_NEAREST)/* FCVT{A,N}U X,S */
+ || (iop == Iop_F32toI64U && irrm == Irrm_ZERO) /* FCVTZU Xd,Sn */
+ || (iop == Iop_F32toI64U && irrm == Irrm_NegINF) /* FCVTMU Xd,Sn */
+ || (iop == Iop_F32toI64U && irrm == Irrm_PosINF) /* FCVTPU Xd,Sn */
+ || (iop == Iop_F32toI64U && irrm == Irrm_NEAREST) /* FCVTNU X,S */
+ || (iop == Iop_F32toI64U && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAU X,S */
/* F64toI32S */
- || (iop == Iop_F64toI32S && irrm == Irrm_ZERO) /* FCVTZS Wd,Dn */
- || (iop == Iop_F64toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Dn */
- || (iop == Iop_F64toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Dn */
- || (iop == Iop_F64toI32S && irrm == Irrm_NEAREST)/* FCVT{A,N}S W,D */
+ || (iop == Iop_F64toI32S && irrm == Irrm_ZERO) /* FCVTZS Wd,Dn */
+ || (iop == Iop_F64toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Dn */
+ || (iop == Iop_F64toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Dn */
+ || (iop == Iop_F64toI32S && irrm == Irrm_NEAREST) /* FCVTNS W,D */
+ || (iop == Iop_F64toI32S && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAS W,D */
/* F64toI32U */
- || (iop == Iop_F64toI32U && irrm == Irrm_ZERO) /* FCVTZU Wd,Dn */
- || (iop == Iop_F64toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Dn */
- || (iop == Iop_F64toI32U && irrm == Irrm_PosINF) /* FCVTPU Wd,Dn */
- || (iop == Iop_F64toI32U && irrm == Irrm_NEAREST)/* FCVT{A,N}U W,D */
+ || (iop == Iop_F64toI32U && irrm == Irrm_ZERO) /* FCVTZU Wd,Dn */
+ || (iop == Iop_F64toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Dn */
+ || (iop == Iop_F64toI32U && irrm == Irrm_PosINF) /* FCVTPU Wd,Dn */
+ || (iop == Iop_F64toI32U && irrm == Irrm_NEAREST) /* FCVTNU W,D */
+ || (iop == Iop_F64toI32U && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAU W,D */
/* F64toI64S */
- || (iop == Iop_F64toI64S && irrm == Irrm_ZERO) /* FCVTZS Xd,Dn */
- || (iop == Iop_F64toI64S && irrm == Irrm_NegINF) /* FCVTMS Xd,Dn */
- || (iop == Iop_F64toI64S && irrm == Irrm_PosINF) /* FCVTPS Xd,Dn */
- || (iop == Iop_F64toI64S && irrm == Irrm_NEAREST)/* FCVT{A,N}S X,D */
+ || (iop == Iop_F64toI64S && irrm == Irrm_ZERO) /* FCVTZS Xd,Dn */
+ || (iop == Iop_F64toI64S && irrm == Irrm_NegINF) /* FCVTMS Xd,Dn */
+ || (iop == Iop_F64toI64S && irrm == Irrm_PosINF) /* FCVTPS Xd,Dn */
+ || (iop == Iop_F64toI64S && irrm == Irrm_NEAREST) /* FCVTNS X,D */
+ || (iop == Iop_F64toI64S && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAS X,D */
/* F64toI64U */
- || (iop == Iop_F64toI64U && irrm == Irrm_ZERO) /* FCVTZU Xd,Dn */
- || (iop == Iop_F64toI64U && irrm == Irrm_NegINF) /* FCVTMU Xd,Dn */
- || (iop == Iop_F64toI64U && irrm == Irrm_PosINF) /* FCVTPU Xd,Dn */
- || (iop == Iop_F64toI64U && irrm == Irrm_NEAREST)/* FCVT{A,N}U X,D */
+ || (iop == Iop_F64toI64U && irrm == Irrm_ZERO) /* FCVTZU Xd,Dn */
+ || (iop == Iop_F64toI64U && irrm == Irrm_NegINF) /* FCVTMU Xd,Dn */
+ || (iop == Iop_F64toI64U && irrm == Irrm_PosINF) /* FCVTPU Xd,Dn */
+ || (iop == Iop_F64toI64U && irrm == Irrm_NEAREST) /* FCVTNU X,D */
+ || (iop == Iop_F64toI64U && irrm == Irrm_NEAREST_TIE_AWAY_0)/* FCVTAU X,D */
) {
/* validated */
} else {
return i;
}
ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
- UChar armRM ) {
+ UChar armRM, Bool tiesToAway ) {
ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
i->tag = ARM64in_VCvtF2I;
i->ARM64in.VCvtF2I.how = how;
i->ARM64in.VCvtF2I.rD = rD;
i->ARM64in.VCvtF2I.rS = rS;
i->ARM64in.VCvtF2I.armRM = armRM;
+ i->ARM64in.VCvtF2I.tiesToAway = tiesToAway;
vassert(armRM <= 3);
return i;
}
---------------- 01 -------------- FCVTP-------- (round to +inf)
---------------- 10 -------------- FCVTM-------- (round to -inf)
---------------- 11 -------------- FCVTZ-------- (round to zero)
+ ---------------- 00 100 ---------- FCVTAS------- (nearest, ties away)
+ ---------------- 00 101 ---------- FCVTAU------- (nearest, ties away)
Rd is Xd when sf==1, Wd when sf==0
Fn is Dn when x==1, Sn when x==0
20:19 carry the rounding mode, using the same encoding as FPCR
+ 18 enable translation to FCVTA{S,U}
*/
UInt rD = iregEnc(i->ARM64in.VCvtF2I.rD);
UInt rN = dregEnc(i->ARM64in.VCvtF2I.rS);
ARM64CvtOp how = i->ARM64in.VCvtF2I.how;
UChar armRM = i->ARM64in.VCvtF2I.armRM;
+ UChar bit18 = i->ARM64in.VCvtF2I.tiesToAway ? 4 : 0;
/* Just handle cases as they show up. */
switch (how) {
case ARM64cvt_F64_I32S: /* FCVTxS Wd, Dn */
- *p++ = X_3_5_8_6_5_5(X000, X11110, X01100000 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X000, X11110, X01100000 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F64_I32U: /* FCVTxU Wd, Dn */
- *p++ = X_3_5_8_6_5_5(X000, X11110, X01100001 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X000, X11110, X01100001 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F64_I64S: /* FCVTxS Xd, Dn */
- *p++ = X_3_5_8_6_5_5(X100, X11110, X01100000 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X100, X11110, X01100000 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F64_I64U: /* FCVTxU Xd, Dn */
- *p++ = X_3_5_8_6_5_5(X100, X11110, X01100001 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X100, X11110, X01100001 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F32_I32S: /* FCVTxS Wd, Sn */
- *p++ = X_3_5_8_6_5_5(X000, X11110, X00100000 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X000, X11110, X00100000 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F32_I32U: /* FCVTxU Wd, Sn */
- *p++ = X_3_5_8_6_5_5(X000, X11110, X00100001 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X000, X11110, X00100001 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F32_I64S: /* FCVTxS Xd, Sn */
- *p++ = X_3_5_8_6_5_5(X100, X11110, X00100000 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X100, X11110, X00100000 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
case ARM64cvt_F32_I64U: /* FCVTxU Xd, Sn */
- *p++ = X_3_5_8_6_5_5(X100, X11110, X00100001 | (armRM << 3),
+ *p++ = X_3_5_8_6_5_5(X100, X11110, X00100001 | (armRM << 3) | bit18,
X000000, rN, rD);
break;
default: