- 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