librz/arch/x86: uplift scalar FP SSE/SSE2 insns to RzIL (#6517)

Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
NOT XVilka 2026-06-17 11:22:04 +08:00 committed by GitHub
parent 62bcb8f6fc
commit 880c8005f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 372 additions and 0 deletions

View file

@ -0,0 +1,231 @@
// SPDX-FileCopyrightText: 2025 RizinOrg <info@rizin.re>
// SPDX-License-Identifier: LGPL-3.0-only
/**
* \file il_sse_ops.inc
*
* Contains the IL implementations for x86 SSE/SSE2 scalar floating point
* instructions, i.e. the ones operating on the low element of an XMM register
* (the `*sd` doubles and `*ss` singles) plus the scalar conversions between
* integers and floats.
*
* The legacy (non-VEX) encodings leave the upper bits of the destination XMM
* register unmodified, which is what these lifters emulate.
*
* Rounding follows the MXCSR default (round to nearest, ties to even). MXCSR is
* not modelled here, so a different rounding mode programmed into MXCSR is not
* reflected, the same way the rest of the x86 lifter does not model every
* control register.
*
* References:
* - Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2
* (ADDSD, ADDSS, ..., CVTSI2SD, CVTTSD2SI, ...)
*/
#include "common.h"
#include <rz_il/rz_il_opbuilder_begin.h>
/**
* \brief Read operand \p op as a scalar float of format \p fmt.
*
* Handles XMM register operands (reinterpreting the low bits of the 128-bit
* register as a float) and memory operands (loading the matching width).
*/
static RzILOpFloat *x86_il_get_scalar_floating_op(X86Op op, RzFloatFormat fmt, int bits, ut64 pc) {
ut8 width = x86_format_to_width(fmt);
if (op.type == X86_OP_REG) {
/* XMM register: reinterpret the low `width` bits as a float */
return BV2F(fmt, CAST(width, IL_FALSE, x86_il_get_reg_bits(op.reg.value, bits, pc)));
}
/* memory operand: load `width` bits and reinterpret them as a float */
return BV2F(fmt, LOADW(width, x86_il_get_memaddr_bits(op.mem, bits, pc)));
}
/**
* \brief Write the scalar float \p val (of format \p fmt) into the low bits of
* the destination XMM register operand \p op, leaving the upper bits unmodified
* (legacy SSE semantics).
*/
static RzILOpEffect *x86_il_set_scalar_floating_op(X86Op op, RZ_OWN RZ_NONNULL RzILOpFloat *val, RzFloatFormat fmt, int bits, ut64 pc) {
ut8 width = x86_format_to_width(fmt);
RzILOpBitVector *result = UNSIGNED(128, F2BV(val));
RzILOpBitVector *old = x86_il_get_reg_bits(op.reg.value, bits, pc);
/* Clear the low `width` bits of the old value while keeping the upper bits,
* then merge in the freshly computed scalar. */
RzILOpBitVector *upper = SHIFTL0(SHIFTR0(old, UN(8, width)), UN(8, width));
return x86_il_set_reg_bits(op.reg.value, LOGOR(upper, result), bits);
}
/* Scalar arithmetic: ADDSD, ADDSS, SUBSD, SUBSS, MULSD, MULSS, DIVSD, DIVSS */
/* dest[scalar] = dest[scalar] <il_op> src[scalar]; upper bits of dest preserved */
#define SSE_SCALAR_ARITHMETIC(il_op, fmt) \
do { \
RzFloatFormat _fmt = (fmt); \
RzILOpFloat *dst = x86_il_get_scalar_floating_op(ins->operands[0], _fmt, analysis->bits, pc); \
RzILOpFloat *src = x86_il_get_scalar_floating_op(ins->operands[1], _fmt, analysis->bits, pc); \
RzILOpFloat *res = il_op(RZ_FLOAT_RMODE_RNE, dst, src); \
return x86_il_set_scalar_floating_op(ins->operands[0], res, _fmt, analysis->bits, pc); \
} while (0)
/**
* ADDSD
* Add the low double precision floating point values
*/
IL_LIFTER(addsd) {
SSE_SCALAR_ARITHMETIC(FADD, RZ_FLOAT_IEEE754_BIN_64);
}
/**
* ADDSS
* Add the low single precision floating point values
*/
IL_LIFTER(addss) {
SSE_SCALAR_ARITHMETIC(FADD, RZ_FLOAT_IEEE754_BIN_32);
}
/**
* SUBSD
* Subtract the low double precision floating point values
*/
IL_LIFTER(subsd) {
SSE_SCALAR_ARITHMETIC(FSUB, RZ_FLOAT_IEEE754_BIN_64);
}
/**
* SUBSS
* Subtract the low single precision floating point values
*/
IL_LIFTER(subss) {
SSE_SCALAR_ARITHMETIC(FSUB, RZ_FLOAT_IEEE754_BIN_32);
}
/**
* MULSD
* Multiply the low double precision floating point values
*/
IL_LIFTER(mulsd) {
SSE_SCALAR_ARITHMETIC(FMUL, RZ_FLOAT_IEEE754_BIN_64);
}
/**
* MULSS
* Multiply the low single precision floating point values
*/
IL_LIFTER(mulss) {
SSE_SCALAR_ARITHMETIC(FMUL, RZ_FLOAT_IEEE754_BIN_32);
}
/**
* DIVSD
* Divide the low double precision floating point values
*/
IL_LIFTER(divsd) {
SSE_SCALAR_ARITHMETIC(FDIV, RZ_FLOAT_IEEE754_BIN_64);
}
/**
* DIVSS
* Divide the low single precision floating point values
*/
IL_LIFTER(divss) {
SSE_SCALAR_ARITHMETIC(FDIV, RZ_FLOAT_IEEE754_BIN_32);
}
/* Integer to scalar float: CVTSI2SD, CVTSI2SS */
/* dest[scalar] = (float) signed_int(src); upper bits of dest preserved */
#define SSE_CVT_SI2F(fmt) \
do { \
RzFloatFormat _fmt = (fmt); \
RzILOpBitVector *int_val = x86_il_get_op(1); \
RzILOpFloat *res = SINT2F(_fmt, RZ_FLOAT_RMODE_RNE, int_val); \
return x86_il_set_scalar_floating_op(ins->operands[0], res, _fmt, analysis->bits, pc); \
} while (0)
/**
* CVTSI2SD
* Convert a signed integer to a double precision floating point value
*/
IL_LIFTER(cvtsi2sd) {
SSE_CVT_SI2F(RZ_FLOAT_IEEE754_BIN_64);
}
/**
* CVTSI2SS
* Convert a signed integer to a single precision floating point value
*/
IL_LIFTER(cvtsi2ss) {
SSE_CVT_SI2F(RZ_FLOAT_IEEE754_BIN_32);
}
/* Scalar float to integer: CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI */
/* dest = (signed int) src[scalar], rounded using \p rmode */
#define SSE_CVT_F2SI(fmt, rmode) \
do { \
RzILOpFloat *f = x86_il_get_scalar_floating_op(ins->operands[1], (fmt), analysis->bits, pc); \
ut32 width = ins->operands[0].size * BITS_PER_BYTE; \
return x86_il_set_op(0, F2SINT(width, rmode, f)); \
} while (0)
/**
* CVTSD2SI
* Convert a double precision floating point value to a signed integer
*/
IL_LIFTER(cvtsd2si) {
SSE_CVT_F2SI(RZ_FLOAT_IEEE754_BIN_64, RZ_FLOAT_RMODE_RNE);
}
/**
* CVTSS2SI
* Convert a single precision floating point value to a signed integer
*/
IL_LIFTER(cvtss2si) {
SSE_CVT_F2SI(RZ_FLOAT_IEEE754_BIN_32, RZ_FLOAT_RMODE_RNE);
}
/**
* CVTTSD2SI
* Convert (with truncation) a double precision floating point value to a signed integer
*/
IL_LIFTER(cvttsd2si) {
SSE_CVT_F2SI(RZ_FLOAT_IEEE754_BIN_64, RZ_FLOAT_RMODE_RTZ);
}
/**
* CVTTSS2SI
* Convert (with truncation) a single precision floating point value to a signed integer
*/
IL_LIFTER(cvttss2si) {
SSE_CVT_F2SI(RZ_FLOAT_IEEE754_BIN_32, RZ_FLOAT_RMODE_RTZ);
}
/* Scalar float to scalar float: CVTSD2SS, CVTSS2SD */
/* dest[scalar] = convert(src[scalar]) from \p src_fmt to \p dst_fmt */
#define SSE_CVT_F2F(src_fmt, dst_fmt) \
do { \
RzFloatFormat _dst = (dst_fmt); \
RzILOpFloat *f = x86_il_get_scalar_floating_op(ins->operands[1], (src_fmt), analysis->bits, pc); \
RzILOpFloat *res = FCONVERT(_dst, RZ_FLOAT_RMODE_RNE, f); \
return x86_il_set_scalar_floating_op(ins->operands[0], res, _dst, analysis->bits, pc); \
} while (0)
/**
* CVTSD2SS
* Convert a double precision floating point value to a single precision floating point value
*/
IL_LIFTER(cvtsd2ss) {
SSE_CVT_F2F(RZ_FLOAT_IEEE754_BIN_64, RZ_FLOAT_IEEE754_BIN_32);
}
/**
* CVTSS2SD
* Convert a single precision floating point value to a double precision floating point value
*/
IL_LIFTER(cvtss2sd) {
SSE_CVT_F2F(RZ_FLOAT_IEEE754_BIN_32, RZ_FLOAT_IEEE754_BIN_64);
}
#include <rz_il/rz_il_opbuilder_end.h>

View file

@ -5,6 +5,7 @@
#include "x86_il.h"
#include "il_ops.inc"
#include "il_fp_ops.inc"
#include "il_sse_ops.inc"
#define COMMON_REGS \
"cs", /* X86_REG_CS */ \
@ -38,6 +39,17 @@
"st6", /* X86_REG_ST6 */ \
"st7" /* X86_REG_ST6 */
/* SSE registers (xmm0-xmm7 are the only ones present in the reg profile). */
#define XMM_REGS \
"xmm0", /* X86_REG_XMM0 */ \
"xmm1", /* X86_REG_XMM1 */ \
"xmm2", /* X86_REG_XMM2 */ \
"xmm3", /* X86_REG_XMM3 */ \
"xmm4", /* X86_REG_XMM4 */ \
"xmm5", /* X86_REG_XMM5 */ \
"xmm6", /* X86_REG_XMM6 */ \
"xmm7" /* X86_REG_XMM7 */
/**
* \brief All registers bound to IL variables for x86 16-bit
*/
@ -74,6 +86,7 @@ const char *x86_bound_regs_32[] = {
"gs", /* X86_REG_GS */
"cr0", /* X86_REG_CR0 */
"dr0", /* X86_REG_DR0 */
XMM_REGS,
NULL
};
@ -106,6 +119,7 @@ const char *x86_bound_regs_64[] = {
"cr0", /* X86_REG_CR0 */
"dr0", /* X86_REG_DR0 */
FPU_REGS,
XMM_REGS,
NULL
};
@ -311,6 +325,24 @@ x86_il_ins x86_ins[X86_INS_MAX_VALUE] = {
[X86_INS_FNOP] = x86_il_fnop,
[X86_INS_FISTTP] = x86_il_fisttp,
/* SSE/SSE2 scalar floating-point instructions */
[X86_INS_ADDSD] = x86_il_addsd,
[X86_INS_ADDSS] = x86_il_addss,
[X86_INS_SUBSD] = x86_il_subsd,
[X86_INS_SUBSS] = x86_il_subss,
[X86_INS_MULSD] = x86_il_mulsd,
[X86_INS_MULSS] = x86_il_mulss,
[X86_INS_DIVSD] = x86_il_divsd,
[X86_INS_DIVSS] = x86_il_divss,
[X86_INS_CVTSI2SD] = x86_il_cvtsi2sd,
[X86_INS_CVTSI2SS] = x86_il_cvtsi2ss,
[X86_INS_CVTSD2SI] = x86_il_cvtsd2si,
[X86_INS_CVTSS2SI] = x86_il_cvtss2si,
[X86_INS_CVTTSD2SI] = x86_il_cvttsd2si,
[X86_INS_CVTTSS2SI] = x86_il_cvttss2si,
[X86_INS_CVTSD2SS] = x86_il_cvtsd2ss,
[X86_INS_CVTSS2SD] = x86_il_cvtss2sd,
/* unimplemented instructions */
[X86_INS_IRET] = x86_il_unimpl,
[X86_INS_INSB] = x86_il_unimpl,

View file

@ -458,6 +458,7 @@
#define X86_INS_PADDQ ZYDIS_MNEMONIC_PADDQ
#define X86_INS_DIVPS ZYDIS_MNEMONIC_DIVPS
#define X86_INS_DIVSS ZYDIS_MNEMONIC_DIVSS
#define X86_INS_DIVSD ZYDIS_MNEMONIC_DIVSD
#define X86_INS_MAXPS ZYDIS_MNEMONIC_MAXPS
#define X86_INS_MAXSS ZYDIS_MNEMONIC_MAXSS
#define X86_INS_MINPS ZYDIS_MNEMONIC_MINPS
@ -470,12 +471,15 @@
#define X86_INS_SQRTSS ZYDIS_MNEMONIC_SQRTSS
#define X86_INS_CVTPI2PS ZYDIS_MNEMONIC_CVTPI2PS
#define X86_INS_CVTSS2SI ZYDIS_MNEMONIC_CVTSS2SI
#define X86_INS_CVTTSS2SI ZYDIS_MNEMONIC_CVTTSS2SI
#define X86_INS_CVTPS2PI ZYDIS_MNEMONIC_CVTPS2PI
#define X86_INS_CVTSI2SS ZYDIS_MNEMONIC_CVTSI2SS
#define X86_INS_CVTSI2SD ZYDIS_MNEMONIC_CVTSI2SD
#define X86_INS_CVTTPD2DQ ZYDIS_MNEMONIC_CVTTPD2DQ
#define X86_INS_CVTPD2PS ZYDIS_MNEMONIC_CVTPD2PS
#define X86_INS_CVTPS2PD ZYDIS_MNEMONIC_CVTPS2PD
#define X86_INS_CVTSD2SI ZYDIS_MNEMONIC_CVTSD2SI
#define X86_INS_CVTTSD2SI ZYDIS_MNEMONIC_CVTTSD2SI
#define X86_INS_CVTSD2SS ZYDIS_MNEMONIC_CVTSD2SS
#define X86_INS_PMOVMSKB ZYDIS_MNEMONIC_PMOVMSKB
#define X86_INS_PSHUFD ZYDIS_MNEMONIC_PSHUFD

View file

@ -2326,3 +2326,19 @@ a "dec ebx" 4b
a "dec ecx" 49
a "dec edi" 4f
a "dec edx" 4a
d "addsd xmm0, xmm1" f20f58c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (+. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "addss xmm0, xmm1" f30f58c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (+. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "subsd xmm0, xmm1" f20f5cc1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (-. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "subss xmm0, xmm1" f30f5cc1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (-. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "mulsd xmm0, xmm1" f20f59c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (*. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "mulss xmm0, xmm1" f30f59c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (*. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "divsd xmm0, xmm1" f20f5ec1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (/. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "divss xmm0, xmm1" f30f5ec1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (/. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "cvtsi2sd xmm0, eax" f20f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin64 rne (var eax))))))
d "cvtsi2ss xmm0, eax" f30f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin32 rne (var eax))))))
d "cvtsd2si eax, xmm0" f20f2dc0 0x0 (set eax (fcast_sint 32 rne (float 1 (cast 64 false (var xmm0)) )))
d "cvtss2si eax, xmm0" f30f2dc0 0x0 (set eax (fcast_sint 32 rne (float 0 (cast 32 false (var xmm0)) )))
d "cvttsd2si eax, xmm0" f20f2cc0 0x0 (set eax (fcast_sint 32 rtz (float 1 (cast 64 false (var xmm0)) )))
d "cvttss2si eax, xmm0" f30f2cc0 0x0 (set eax (fcast_sint 32 rtz (float 0 (cast 32 false (var xmm0)) )))
d "cvtsd2ss xmm0, xmm1" f20f5ac1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (fconvert ieee754-bin32 rne (float 1 (cast 64 false (var xmm1)) ))))))
d "cvtss2sd xmm0, xmm1" f30f5ac1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fconvert ieee754-bin64 rne (float 0 (cast 32 false (var xmm1)) ))))))

View file

@ -1118,3 +1118,25 @@ a "fnstsw ax" dfe0 0x0 (set rax (| (& (var rax) (~ (bv 64 0xffff))) (cast 64 fal
a "fsave dword [rax]" 9bdd30
a "fnsave dword [rax]" dd30
aB "fnsave dword [rdi + rdi*8]" dd34ff
d "addsd xmm0, xmm1" f20f58c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (+. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "addss xmm0, xmm1" f30f58c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (+. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "subsd xmm0, xmm1" f20f5cc1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (-. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "subss xmm0, xmm1" f30f5cc1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (-. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "mulsd xmm0, xmm1" f20f59c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (*. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "mulss xmm0, xmm1" f30f59c1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (*. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "divsd xmm0, xmm1" f20f5ec1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (/. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm1)) ))))))
d "divss xmm0, xmm1" f30f5ec1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (/. rne (float 0 (cast 32 false (var xmm0)) ) (float 0 (cast 32 false (var xmm1)) ))))))
d "cvtsi2sd xmm0, rax" f2480f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin64 rne (var rax))))))
d "cvtsi2sd xmm0, eax" f20f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin64 rne (cast 32 false (var rax)))))))
d "cvtsi2ss xmm0, rax" f3480f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin32 rne (var rax))))))
d "cvtsi2ss xmm0, eax" f30f2ac0 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin32 rne (cast 32 false (var rax)))))))
d "cvtsd2si rax, xmm0" f2480f2dc0 0x0 (set rax (fcast_sint 64 rne (float 1 (cast 64 false (var xmm0)) )))
d "cvtsd2si eax, xmm0" f20f2dc0 0x0 (set rax (cast 64 false (fcast_sint 32 rne (float 1 (cast 64 false (var xmm0)) ))))
d "cvtss2si rax, xmm0" f3480f2dc0 0x0 (set rax (fcast_sint 64 rne (float 0 (cast 32 false (var xmm0)) )))
d "cvtss2si eax, xmm0" f30f2dc0 0x0 (set rax (cast 64 false (fcast_sint 32 rne (float 0 (cast 32 false (var xmm0)) ))))
d "cvttsd2si rax, xmm0" f2480f2cc0 0x0 (set rax (fcast_sint 64 rtz (float 1 (cast 64 false (var xmm0)) )))
d "cvttsd2si eax, xmm0" f20f2cc0 0x0 (set rax (cast 64 false (fcast_sint 32 rtz (float 1 (cast 64 false (var xmm0)) ))))
d "cvttss2si rax, xmm0" f3480f2cc0 0x0 (set rax (fcast_sint 64 rtz (float 0 (cast 32 false (var xmm0)) )))
d "cvttss2si eax, xmm0" f30f2cc0 0x0 (set rax (cast 64 false (fcast_sint 32 rtz (float 0 (cast 32 false (var xmm0)) ))))
d "cvtsd2ss xmm0, xmm1" f20f5ac1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x20) false) (bv 8 0x20) false) (cast 128 false (fbits (fconvert ieee754-bin32 rne (float 1 (cast 64 false (var xmm1)) ))))))
d "cvtss2sd xmm0, xmm1" f30f5ac1 0x0 (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fconvert ieee754-bin64 rne (float 0 (cast 32 false (var xmm1)) ))))))

View file

@ -105,3 +105,70 @@ EOF
EXPECT=Hello from RzIL!
EXPECT_ERR=
RUN
NAME=x86 SSE2 scalar floating-point IL
FILE=malloc://0x100
CMDS=<<EOF
e asm.arch=x86
e asm.bits=64
e analysis.arch=x86
e analysis.bits=64
# IL generation for the instructions listed in the issue
wx f2490f2accf2490f2ac0f20f5e442408f20f58c0
ao 4~rzil
# emulate the issue's sequence: r12=3, r8=20, [rsp+8]=2.0
# -> xmm1=3.0, xmm0=((20.0)/2.0 + itself)=20.0
s 0
aezi
ar r12=3
ar r8=20
ar rsp=0x40
wv8 0x4000000000000000 @ 0x48
aezsu 0x14
ar xmm1
ar xmm0
# mulss: 3.0f * 2.0f = 6.0f
wx f30f59c1 @ 0
s 0
aezi
ar xmm0=0x40400000
ar xmm1=0x40000000
aezs
ar xmm0
# subsd: 5.0 - 1.0 = 4.0
wx f20f5cc1 @ 0
s 0
aezi
ar xmm0=0x4014000000000000
ar xmm1=0x3ff0000000000000
aezs
ar xmm0
# cvttsd2si: trunc(3.9) = 3
wx f2480f2cc0 @ 0
s 0
aezi
ar xmm0=0x400f333333333333
aezs
ar rax
# cvtsd2ss: double 1.5 -> single 1.5, upper bits of dest preserved
wx f20f5ac1 @ 0
s 0
aezi
ar xmm0=0x4018000000000000
ar xmm1=0x3ff8000000000000
aezs
ar xmm0
EOF
EXPECT=<<EOF
rzil: (set xmm1 (| (<< (>> (var xmm1) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin64 rne (var r12))))))
rzil: (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (fcast_sfloat ieee754-bin64 rne (var r8))))))
rzil: (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (/. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (loadw 0 64 (+ (var rsp) (bv 64 0x8))) ))))))
rzil: (set xmm0 (| (<< (>> (var xmm0) (bv 8 0x40) false) (bv 8 0x40) false) (cast 128 false (fbits (+. rne (float 1 (cast 64 false (var xmm0)) ) (float 1 (cast 64 false (var xmm0)) ))))))
xmm1 = 0x00000000000000004008000000000000
xmm0 = 0x00000000000000004034000000000000
xmm0 = 0x00000000000000000000000040c00000
xmm0 = 0x00000000000000004010000000000000
rax = 0x0000000000000003
xmm0 = 0x0000000000000000401800003fc00000
EOF
RUN