- fix moving floats between GPR and XMM registers
- implemented FSUB FMUL and FDIV, cannot be fully tested yet
- implemented FCMPL

- missing : FNEG, FREM, and more importantly functions returning float
are not doing it properly yet.

Signed-off-by: Arthur Huillet <arthur.huil...@free.fr>
---
 arch/x86/emit-code.c                |   93 +++++++++++++++++++++++------------
 arch/x86/include/arch/instruction.h |    9 +++-
 arch/x86/insn-selector_32.brg       |   65 ++++++++++++++++++++----
 arch/x86/lir-printer.c              |   43 +++++++++++++++--
 arch/x86/use-def.c                  |    9 +++-
 test/arch-x86/emit-code-test_32.c   |    2 +-
 6 files changed, 170 insertions(+), 51 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index a348ab3..bed1900 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -532,7 +532,9 @@ __emit_membase(struct buffer *buf, unsigned char opc,
        else
                rm = __encode_reg(base_reg);
 
-       if (is_imm_8(disp))
+       if (disp == 0)
+               mod = 0x00;
+       else if (is_imm_8(disp))
                mod = 0x01;
        else
                mod = 0x02;
@@ -543,7 +545,8 @@ __emit_membase(struct buffer *buf, unsigned char opc,
        if (needs_sib)
                emit(buf, encode_sib(0x00, 0x04, __encode_reg(base_reg)));
 
-       emit_imm(buf, disp);
+       if (disp)
+               emit_imm(buf, disp);
 }
 
 static void
@@ -680,17 +683,7 @@ static void emit_mov_imm_reg(struct buffer *buf, struct 
operand *src,
 static void emit_mov_imm_membase(struct buffer *buf, struct operand *src,
                                 struct operand *dest)
 {
-       unsigned long mod = 0x00;
-
-       emit(buf, 0xc7);
-
-       if (dest->disp != 0)
-               mod = 0x01;
-
-       emit(buf, encode_modrm(mod, 0x00, encode_reg(&dest->base_reg)));
-
-       if (dest->disp != 0)
-               emit(buf, dest->disp);
+       __emit_membase(buf, 0xc7, mach_reg(&dest->base_reg), dest->disp, 0);
 
        emit_imm32(buf, src->imm);
 }
@@ -698,17 +691,7 @@ static void emit_mov_imm_membase(struct buffer *buf, 
struct operand *src,
 static void
 emit_mov_reg_membase(struct buffer *buf, struct operand *src, struct operand 
*dest)
 {
-       int mod;
-
-       if (is_imm_8(dest->disp))
-               mod = 0x01;
-       else
-               mod = 0x02;
-
-       emit(buf, 0x89);
-       emit(buf, encode_modrm(mod, encode_reg(&src->reg), 
encode_reg(&dest->base_reg)));
-
-       emit_imm(buf, dest->disp);
+       __emit_membase(buf, 0x89, mach_reg(&dest->base_reg), dest->disp, 
encode_reg(&src->reg));
 }
 
 static void emit_mov_reg_memlocal(struct buffer *buf, struct operand *src,
@@ -889,6 +872,28 @@ static void emit_fadd_reg_reg(struct buffer *buf,
        emit_reg_reg(buf, 0x58, dest, src);
 }
 
+static void emit_fsub_reg_reg(struct buffer *buf,
+                            struct operand *src, struct operand *dest)
+{
+       emit(buf, 0xf3);
+       emit(buf, 0x0f);
+       emit_reg_reg(buf, 0x5c, dest, src);
+}
+static void emit_fmul_reg_reg(struct buffer *buf,
+                            struct operand *src, struct operand *dest)
+{
+       emit(buf, 0xf3);
+       emit(buf, 0x0f);
+       emit_reg_reg(buf, 0x59, dest, src);
+}
+static void emit_fdiv_reg_reg(struct buffer *buf,
+                            struct operand *src, struct operand *dest)
+{
+       emit(buf, 0xf3);
+       emit(buf, 0x0f);
+       emit_reg_reg(buf, 0x5e, dest, src);
+}
+
 static void emit_add_membase_reg(struct buffer *buf,
                                 struct operand *src, struct operand *dest)
 {
@@ -1142,20 +1147,36 @@ static void emit_exception_test(struct buffer *buf, 
enum machine_reg reg)
        __emit_test_membase_reg(buf, reg, 0, reg);
 }
 
-static void emit_mov_gpr_to_xmm(struct buffer *buf, struct operand *src,
+static void emit_conv_gpr_to_fpu(struct buffer *buf, struct operand *src,
+                               struct operand *dest)
+{
+       emit(buf, 0xf3);
+       emit(buf, 0x0f);
+       emit_reg_reg(buf, 0x2a, src, dest);
+}
+
+static void emit_conv_fpu_to_gpr(struct buffer *buf, struct operand *src,
                                struct operand *dest)
 {
        emit(buf, 0xf3);
        emit(buf, 0x0f);
-       emit_reg_reg(buf, 0x2a, dest, src);
+       emit_reg_reg(buf, 0x2d, src, dest);
 }
 
-static void emit_mov_xmm_to_gpr(struct buffer *buf, struct operand *src,
+static void emit_mov_membase_xmm(struct buffer *buf, struct operand *src,
                                struct operand *dest)
 {
        emit(buf, 0xf3);
        emit(buf, 0x0f);
-       emit_reg_reg(buf, 0x2d, dest, src);
+       emit_membase_reg(buf, 0x10, src, dest);
+}
+
+static void emit_mov_xmm_membase(struct buffer *buf, struct operand *src,
+                               struct operand *dest)
+{
+       emit(buf, 0xf3);
+       emit(buf, 0x0f);
+       emit_membase_reg(buf, 0x11, dest, src);
 }
 
 struct emitter emitters[] = {
@@ -1176,8 +1197,13 @@ struct emitter emitters[] = {
        DECL_EMITTER(INSN_DIV_MEMBASE_REG, emit_div_membase_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_DIV_REG_REG, emit_div_reg_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_FADD_REG_REG, emit_fadd_reg_reg, TWO_OPERANDS),
-       DECL_EMITTER(INSN_MOV_GPR_TO_XMM, emit_mov_gpr_to_xmm, TWO_OPERANDS),
-       DECL_EMITTER(INSN_MOV_XMM_TO_GPR, emit_mov_xmm_to_gpr, TWO_OPERANDS),
+       DECL_EMITTER(INSN_FSUB_REG_REG, emit_fsub_reg_reg, TWO_OPERANDS),
+       DECL_EMITTER(INSN_FMUL_REG_REG, emit_fmul_reg_reg, TWO_OPERANDS),
+       DECL_EMITTER(INSN_FDIV_REG_REG, emit_fdiv_reg_reg, TWO_OPERANDS),
+       DECL_EMITTER(INSN_CONV_GPR_TO_FPU, emit_conv_gpr_to_fpu, TWO_OPERANDS),
+       DECL_EMITTER(INSN_CONV_FPU_TO_GPR, emit_conv_fpu_to_gpr, TWO_OPERANDS),
+       DECL_EMITTER(INSN_MOV_MEMBASE_XMM, emit_mov_membase_xmm, TWO_OPERANDS),
+       DECL_EMITTER(INSN_MOV_XMM_MEMBASE, emit_mov_xmm_membase, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_IMM_MEMBASE, emit_mov_imm_membase, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_IMM_REG, emit_mov_imm_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_MEMLOCAL_REG, emit_mov_memlocal_reg, 
TWO_OPERANDS),
@@ -1655,7 +1681,9 @@ static void __emit_membase(struct buffer *buf,
        else
                rm = __base_reg;
 
-       if (is_imm_8(disp))
+       if (disp == 0)
+               mod = 0x00;
+       else if (is_imm_8(disp))
                mod = 0x01;
        else
                mod = 0x02;
@@ -1676,7 +1704,8 @@ static void __emit_membase(struct buffer *buf,
        if (needs_sib)
                emit(buf, encode_sib(0x00, 0x04, __base_reg));
 
-       emit_imm(buf, disp);
+       if (disp)
+               emit_imm(buf, disp);
 }
 
 static void __emit64_push_membase(struct buffer *buf,
diff --git a/arch/x86/include/arch/instruction.h 
b/arch/x86/include/arch/instruction.h
index 0693d89..d0b52db 100644
--- a/arch/x86/include/arch/instruction.h
+++ b/arch/x86/include/arch/instruction.h
@@ -71,8 +71,11 @@ enum insn_type {
        INSN_DIV_MEMBASE_REG,
        INSN_DIV_REG_REG,
        INSN_FADD_REG_REG,
-       INSN_MOV_GPR_TO_XMM,
-       INSN_MOV_XMM_TO_GPR,
+       INSN_FMUL_REG_REG,
+       INSN_FDIV_REG_REG,
+       INSN_FSUB_REG_REG,
+       INSN_CONV_FPU_TO_GPR,
+       INSN_CONV_GPR_TO_FPU,
        INSN_JE_BRANCH,
        INSN_JGE_BRANCH,
        INSN_JG_BRANCH,
@@ -94,6 +97,8 @@ enum insn_type {
        INSN_MOV_REG_MEMLOCAL,
        INSN_MOV_FREG_MEMLOCAL,
        INSN_MOV_REG_REG,
+       INSN_MOV_MEMBASE_XMM,
+       INSN_MOV_XMM_MEMBASE,
        INSN_MOVSX_REG_REG,
        INSN_MUL_MEMBASE_EAX,
        INSN_MUL_REG_EAX,
diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 6725bb4..35ed3d3 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -139,38 +139,44 @@ static enum insn_type br_binop_to_insn_type(enum 
binary_operator binop)
 freg:  EXPR_FVALUE     0
 {
        struct expression *expr;
-       struct var_info *result, *gpr;
+       struct var_info *result, *esp;
 
        expr = to_expr(tree);
 
-       gpr = get_var(s->b_parent);
+       esp = get_fixed_var(s->b_parent, REG_ESP);
        result = get_fpu_var(s->b_parent);
        state->reg1 = result;
 
-       select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, 
float_to_uint32(expr->fvalue), gpr));
-       select_insn(s, tree, reg_reg_insn(INSN_MOV_GPR_TO_XMM, gpr, result));
+       select_insn(s, tree, imm_membase_insn(INSN_MOV_IMM_MEMBASE, 
float_to_uint32(expr->fvalue), esp, -4));
+       select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_XMM, esp, -4, 
result));
 }
 
 reg:   freg 1
 {
-       struct var_info *result, *in;
+       struct var_info *result, *in, *esp;
 
        in = state->reg1;
        result = get_var(s->b_parent);
        state->reg1 = result;
 
-       select_insn(s, tree, reg_reg_insn(INSN_MOV_XMM_TO_GPR, in, result));
+       esp = get_fixed_var(s->b_parent, REG_ESP);
+
+       select_insn(s, tree, reg_membase_insn(INSN_MOV_XMM_MEMBASE, in, esp, 
-4));
+       select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_REG, esp, -4, 
result));
 }
 
 freg:  reg 1
 {
-       struct var_info *result, *in;
+       struct var_info *result, *in, *esp;
 
        in = state->reg1;
        result = get_fpu_var(s->b_parent);
        state->reg1 = result;
 
-       select_insn(s, tree, reg_reg_insn(INSN_MOV_GPR_TO_XMM, in, result));
+       esp = get_fixed_var(s->b_parent, REG_ESP);
+
+       select_insn(s, tree, reg_membase_insn(INSN_MOV_REG_MEMBASE, in, esp, 
-4));
+       select_insn(s, tree, membase_reg_insn(INSN_MOV_MEMBASE_XMM, esp, -4, 
result));
 }
 
 reg:   EXPR_VALUE      0
@@ -322,6 +328,16 @@ reg:       OP_SUB(reg, reg) 1
        }
 }
 
+freg:  OP_FSUB(freg, freg) 1
+{
+       struct expression *expr;
+
+       expr = to_expr(tree);
+
+       state->reg1 = state->left->reg1;
+       binop_reg_reg_low(state, s, tree, INSN_FSUB_REG_REG);
+}
+
 reg:   OP_MUL(reg, EXPR_LOCAL) 1
 {
        struct var_info *eax;
@@ -341,6 +357,14 @@ reg:       OP_MUL(reg, reg) 1
        select_insn(s, tree, reg_reg_insn(INSN_MUL_REG_REG, state->left->reg1, 
state->right->reg1));
 }
 
+freg:  OP_FMUL(reg, reg) 1
+{
+       state->reg1 = state->left->reg1;
+
+       select_insn(s, tree, reg_reg_insn(INSN_FMUL_REG_REG, 
state->right->reg1, state->left->reg1));
+}
+
+
 reg:   OP_MUL_64(reg, reg) 1
 {
        struct var_info *eax, *edx, *tmp1;
@@ -384,6 +408,13 @@ reg:       OP_DIV(reg, reg) 1
        select_insn(s, tree, reg_reg_insn(INSN_DIV_REG_REG, state->right->reg1, 
result));
 }
 
+freg:  OP_FDIV(reg, reg) 1
+{
+       state->reg1 = state->left->reg1;
+
+       select_insn(s, tree, reg_reg_insn(INSN_FDIV_REG_REG, 
state->right->reg1, state->left->reg1));
+}
+
 reg:   OP_DIV_64(reg, reg) 1
 {
        emulate_op_64(state, s, tree, emulate_ldiv, J_LONG);
@@ -716,8 +747,22 @@ reg:       EXPR_INVOKEVIRTUAL(arg) 1
 
 reg:   OP_CMPL(reg, reg) 1
 {
-       NOT_IMPLEMENTED;
-       state->reg1 = state->left->reg1;
+       struct var_info *esp, *eax;
+
+       state->reg1 = get_var(s->b_parent);
+       
+       esp = get_fixed_var(s->b_parent, REG_ESP);
+       eax = get_fixed_var(s->b_parent, REG_EAX);
+
+       select_insn(s, tree, reg_membase_insn(INSN_MOV_XMM_MEMBASE, 
state->left->reg1, esp, -8));
+       select_insn(s, tree, reg_membase_insn(INSN_MOV_XMM_MEMBASE, 
state->right->reg1, esp, -4));
+
+       select_insn(s, tree, imm_reg_insn(INSN_SUB_IMM_REG, 8, esp));
+
+       select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
emulate_fcmpl));
+       method_args_cleanup(s, tree, 2);
+
+       select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1));
 }
 
 reg:   OP_CMP(reg, reg) 1
diff --git a/arch/x86/lir-printer.c b/arch/x86/lir-printer.c
index 13ce2a7..fc99cdd 100644
--- a/arch/x86/lir-printer.c
+++ b/arch/x86/lir-printer.c
@@ -218,6 +218,24 @@ static int print_fadd_reg_reg(struct string *str, struct 
insn *insn)
        return print_reg_reg(str, insn);
 }
 
+static int print_fsub_reg_reg(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_reg_reg(str, insn);
+}
+
+static int print_fmul_reg_reg(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_reg_reg(str, insn);
+}
+
+static int print_fdiv_reg_reg(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_reg_reg(str, insn);
+}
+
 static int print_and_membase_reg(struct string *str, struct insn *insn)
 {
        print_func_name(str);
@@ -280,13 +298,25 @@ static int print_div_reg_reg(struct string *str, struct 
insn *insn)
        return print_reg_reg(str, insn);
 }
 
-static int print_mov_gpr_to_xmm(struct string *str, struct insn *insn)
+static int print_mov_membase_xmm(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_membase_reg(str, insn);
+}
+
+static int print_mov_xmm_membase(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_reg_membase(str, insn);
+}
+
+static int print_conv_fpu_to_gpr(struct string *str, struct insn *insn)
 {
        print_func_name(str);
        return print_reg_reg(str, insn);
 }
 
-static int print_mov_xmm_to_gpr(struct string *str, struct insn *insn)
+static int print_conv_gpr_to_fpu(struct string *str, struct insn *insn)
 {
        print_func_name(str);
        return print_reg_reg(str, insn);
@@ -594,8 +624,13 @@ static print_insn_fn insn_printers[] = {
        [INSN_DIV_MEMBASE_REG] = print_div_membase_reg,
        [INSN_DIV_REG_REG] = print_div_reg_reg,
        [INSN_FADD_REG_REG] = print_fadd_reg_reg,
-       [INSN_MOV_GPR_TO_XMM] = print_mov_gpr_to_xmm,
-       [INSN_MOV_XMM_TO_GPR] = print_mov_xmm_to_gpr,
+       [INSN_FSUB_REG_REG] = print_fsub_reg_reg,
+       [INSN_FMUL_REG_REG] = print_fmul_reg_reg,
+       [INSN_FDIV_REG_REG] = print_fdiv_reg_reg,
+       [INSN_MOV_MEMBASE_XMM] = print_mov_membase_xmm,
+       [INSN_MOV_XMM_MEMBASE] = print_mov_xmm_membase,
+       [INSN_CONV_FPU_TO_GPR] = print_conv_fpu_to_gpr,
+       [INSN_CONV_GPR_TO_FPU] = print_conv_gpr_to_fpu,
        [INSN_JE_BRANCH] = print_je_branch,
        [INSN_JGE_BRANCH] = print_jge_branch,
        [INSN_JG_BRANCH] = print_jg_branch,
diff --git a/arch/x86/use-def.c b/arch/x86/use-def.c
index e85769e..73fd389 100644
--- a/arch/x86/use-def.c
+++ b/arch/x86/use-def.c
@@ -46,8 +46,13 @@ static struct insn_info insn_infos[] = {
        DECLARE_INFO(INSN_DIV_MEMBASE_REG, USE_SRC | DEF_DST | DEF_EAX | 
DEF_EDX),
        DECLARE_INFO(INSN_DIV_REG_REG, USE_SRC | DEF_DST | DEF_EAX | DEF_EDX),
        DECLARE_INFO(INSN_FADD_REG_REG, USE_SRC | DEF_DST),
-       DECLARE_INFO(INSN_MOV_GPR_TO_XMM, USE_SRC | DEF_DST),
-       DECLARE_INFO(INSN_MOV_XMM_TO_GPR, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_FSUB_REG_REG, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_FMUL_REG_REG, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_FDIV_REG_REG, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_CONV_GPR_TO_FPU, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_CONV_FPU_TO_GPR, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_MOV_MEMBASE_XMM, USE_SRC | DEF_DST),
+       DECLARE_INFO(INSN_MOV_XMM_MEMBASE, USE_SRC | DEF_DST),
        DECLARE_INFO(INSN_JE_BRANCH, USE_NONE | DEF_NONE),
        DECLARE_INFO(INSN_JGE_BRANCH, USE_NONE | DEF_NONE),
        DECLARE_INFO(INSN_JG_BRANCH, USE_NONE | DEF_NONE),
diff --git a/test/arch-x86/emit-code-test_32.c 
b/test/arch-x86/emit-code-test_32.c
index 7c7b320..f024f62 100644
--- a/test/arch-x86/emit-code-test_32.c
+++ b/test/arch-x86/emit-code-test_32.c
@@ -250,7 +250,7 @@ void test_emit_mov_disp_reg(void)
        assert_emit_insn_3(0x8b, 0x5D, 0x08, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_EBP, 0x08, &VAR_EBX));
        assert_emit_insn_3(0x8b, 0x4D, 0x08, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_EBP, 0x08, &VAR_ECX));
        assert_emit_insn_3(0x8b, 0x55, 0x08, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_EBP, 0x08, &VAR_EDX));
-       assert_emit_insn_4(0x8b, 0x44, 0x24, 0x00, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_ESP, 0, &VAR_EAX));
+       assert_emit_insn_3(0x8b, 0x04, 0x24, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_ESP, 0, &VAR_EAX));
 
        assert_emit_insn_6(0x8b, 0x80, 0x50, 0x02, 0x00, 0x00, 
membase_reg_insn(INSN_MOV_MEMBASE_REG, &VAR_EAX, 0x250, &VAR_EAX));
 }
-- 
1.6.3.3



------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to