diff --git a/librz/arch/isa/x86/il_sse_ops.inc b/librz/arch/isa/x86/il_sse_ops.inc new file mode 100644 index 0000000000..b1c72345e2 --- /dev/null +++ b/librz/arch/isa/x86/il_sse_ops.inc @@ -0,0 +1,231 @@ +// SPDX-FileCopyrightText: 2025 RizinOrg +// 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 + +/** + * \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] 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 diff --git a/librz/arch/isa/x86/x86_il.c b/librz/arch/isa/x86/x86_il.c index 475d9eb88d..652e29dfe2 100644 --- a/librz/arch/isa/x86/x86_il.c +++ b/librz/arch/isa/x86/x86_il.c @@ -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, diff --git a/librz/arch/isa/x86/x86_mnemonics.h b/librz/arch/isa/x86/x86_mnemonics.h index 61a513abc0..5f796039e0 100644 --- a/librz/arch/isa/x86/x86_mnemonics.h +++ b/librz/arch/isa/x86/x86_mnemonics.h @@ -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 diff --git a/test/db/asm/x86_32 b/test/db/asm/x86_32 index 6e791dd857..60f8989a34 100644 --- a/test/db/asm/x86_32 +++ b/test/db/asm/x86_32 @@ -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)) )))))) diff --git a/test/db/asm/x86_64 b/test/db/asm/x86_64 index 105fa3be54..61e5ad4086 100644 --- a/test/db/asm/x86_64 +++ b/test/db/asm/x86_64 @@ -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)) )))))) diff --git a/test/db/rzil/x86 b/test/db/rzil/x86 index b39176a582..d08890c854 100644 --- a/test/db/rzil/x86 +++ b/test/db/rzil/x86 @@ -105,3 +105,70 @@ EOF EXPECT=Hello from RzIL! EXPECT_ERR= RUN + +NAME=x86 SSE2 scalar floating-point IL +FILE=malloc://0x100 +CMDS=< 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=<> (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