diff --git a/librz/analysis/arch/x86/common.c b/librz/analysis/arch/x86/common.c index c9234dde10f..a33052c63ad 100644 --- a/librz/analysis/arch/x86/common.c +++ b/librz/analysis/arch/x86/common.c @@ -1249,6 +1249,7 @@ RzILOpPure *x86_il_get_floating_operand_bits(X86Op op, int analysis_bits, ut64 p } else { RZ_LOG_ERROR("x86: RzIL: Invalid register passed as a floating point operand: %d\n", op.reg); } + break; case X86_OP_MEM: switch (op.size) { /* ~Duff's~ DMaroo's device */ @@ -1258,6 +1259,7 @@ RzILOpPure *x86_il_get_floating_operand_bits(X86Op op, int analysis_bits, ut64 p default: RZ_LOG_ERROR("x86: RzIL: Invalid memory operand width for a floating point operand: %d\n", op.size); } + break; case X86_OP_INVALID: case X86_OP_IMM: #if CS_API_MAJOR <= 3 diff --git a/librz/analysis/arch/x86/il_fp_ops.inc b/librz/analysis/arch/x86/il_fp_ops.inc index 1276afb4090..9e7afcbab12 100644 --- a/librz/analysis/arch/x86/il_fp_ops.inc +++ b/librz/analysis/arch/x86/il_fp_ops.inc @@ -207,3 +207,28 @@ IL_LIFTER(fldlg2) { IL_LIFTER(fldln2) { return SEQ2(INIT_RMODE("rmode"), fpu_stack_push_val(math_const_to_float(FPU_LN2))); } + +/** + * FXCH + * Exchange the contents of FPU stack register with ST(0) + */ +IL_LIFTER(fxch) { + X86Reg reg; + + if (ins->structure->op_count == 0) { + /* Use ST1 as the default reg in case no operand is provided. */ + reg = X86_REG_ST1; + } else { + reg = ins->structure->operands[0].reg; + } + + /* TODO: The IL generated from the following code is too verbose because of + many rounding checks, there are ways to remove this sort of rounding checks, + but it doesn't matter for now so I'm not bothering with it. */ + return SEQ4( + SETL("tmp", x86_il_get_st_reg(X86_REG_ST0)), + x86_il_set_st_reg(X86_REG_ST0, x86_il_get_st_reg(reg)), + x86_il_set_st_reg(reg, VARL("tmp")), + x86_il_set_fpu_flag(X86_FPU_C1, IL_FALSE) + ); +} diff --git a/librz/analysis/arch/x86/x86_il.c b/librz/analysis/arch/x86/x86_il.c index 42517dbb9c0..ed8eb297b22 100644 --- a/librz/analysis/arch/x86/x86_il.c +++ b/librz/analysis/arch/x86/x86_il.c @@ -259,7 +259,8 @@ x86_il_ins x86_ins[X86_INS_ENDING] = { [X86_INS_FLDL2E] = x86_il_fldl2e, [X86_INS_FLDPI] = x86_il_fldpi, [X86_INS_FLDLG2] = x86_il_fldlg2, - [X86_INS_FLDLN2] = x86_il_fldln2 + [X86_INS_FLDLN2] = x86_il_fldln2, + [X86_INS_FXCH] = x86_il_fxch, }; void label_int(RzILVM *vm, RzILOpEffect *op);