Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/emit-code.c | 18 ++++++++++ arch/x86/include/arch/instruction.h | 2 + arch/x86/insn-selector.brg | 65 +++++++++++++++++++++++++++++++--- arch/x86/lir-printer.c | 14 +++++++ arch/x86/use-def.c | 2 + include/jit/expression.h | 9 +++++ jit/expression.c | 49 ++++++++++++++++++++++++++ jit/tree-printer.c | 4 ++ jit/typeconv-bc.c | 14 ++++++- test/jit/typeconv-bc-test.c | 12 +++--- 10 files changed, 175 insertions(+), 14 deletions(-)
diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c index e2fa035..a59523e 100644 --- a/arch/x86/emit-code.c +++ b/arch/x86/emit-code.c @@ -1466,6 +1466,22 @@ static void emit_exception_test(struct buffer *buf, enum machine_reg reg) __emit_test_membase_reg(buf, reg, 0, reg); } +static void emit_conv_xmm_to_xmm64(struct buffer *buf, struct operand *src, + struct operand *dest) +{ + emit(buf, 0xf3); + emit(buf, 0x0f); + emit_reg_reg(buf, 0x5a, dest, src); +} + +static void emit_conv_xmm64_to_xmm(struct buffer *buf, struct operand *src, + struct operand *dest) +{ + emit(buf, 0xf2); + emit(buf, 0x0f); + emit_reg_reg(buf, 0x5a, dest, src); +} + static void emit_conv_gpr_to_fpu(struct buffer *buf, struct operand *src, struct operand *dest) { @@ -1676,6 +1692,8 @@ struct emitter emitters[] = { DECL_EMITTER(INSN_CONV_GPR_TO_FPU64, emit_conv_gpr_to_fpu64, TWO_OPERANDS), DECL_EMITTER(INSN_CONV_FPU_TO_GPR, emit_conv_fpu_to_gpr, TWO_OPERANDS), DECL_EMITTER(INSN_CONV_FPU64_TO_GPR, emit_conv_fpu64_to_gpr, TWO_OPERANDS), + DECL_EMITTER(INSN_CONV_XMM_TO_XMM64, emit_conv_xmm_to_xmm64, TWO_OPERANDS), + DECL_EMITTER(INSN_CONV_XMM64_TO_XMM, emit_conv_xmm64_to_xmm, TWO_OPERANDS), DECL_EMITTER(INSN_JMP_MEMINDEX, emit_jmp_memindex, SINGLE_OPERAND), DECL_EMITTER(INSN_MOV_MEMBASE_XMM, emit_mov_membase_xmm, TWO_OPERANDS), DECL_EMITTER(INSN_MOV_64_MEMBASE_XMM, emit_mov_64_membase_xmm, TWO_OPERANDS), diff --git a/arch/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index cb65c1d..feb8dbe 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -90,6 +90,8 @@ enum insn_type { INSN_CONV_FPU64_TO_GPR, INSN_CONV_GPR_TO_FPU, INSN_CONV_GPR_TO_FPU64, + INSN_CONV_XMM_TO_XMM64, + INSN_CONV_XMM64_TO_XMM, INSN_JE_BRANCH, INSN_JGE_BRANCH, INSN_JG_BRANCH, diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg index db38e44..3860422 100644 --- a/arch/x86/insn-selector.brg +++ b/arch/x86/insn-selector.brg @@ -1438,6 +1438,28 @@ reg: EXPR_CONVERSION(reg) } } +freg: EXPR_CONVERSION_FLOAT_TO_DOUBLE(freg) +{ + struct expression *expr, *src; + + expr = to_expr(tree); + src = to_expr(expr->from_expression); + + state->reg1 = get_var(s->b_parent, J_DOUBLE); + select_insn(s, tree, reg_reg_insn(INSN_CONV_XMM_TO_XMM64, state->left->reg1, state->reg1)); +} + +freg: EXPR_CONVERSION_DOUBLE_TO_FLOAT(freg) +{ + struct expression *expr, *src; + + expr = to_expr(tree); + src = to_expr(expr->from_expression); + + state->reg1 = get_var(s->b_parent, J_FLOAT); + select_insn(s, tree, reg_reg_insn(INSN_CONV_XMM64_TO_XMM, state->left->reg1, state->reg1)); +} + freg: EXPR_CONVERSION_TO_FLOAT(reg) { struct expression *expr, *src; @@ -1445,13 +1467,28 @@ freg: EXPR_CONVERSION_TO_FLOAT(reg) expr = to_expr(tree); src = to_expr(expr->from_expression); - if (src->vm_type == J_INT && expr->vm_type == J_FLOAT) { + assert(expr->vm_type == J_FLOAT); + + if (src->vm_type == J_INT) { state->reg1 = get_var(s->b_parent, J_FLOAT); select_insn(s, tree, reg_reg_insn(INSN_CONV_GPR_TO_FPU, state->left->reg1, state->reg1)); - } else if (src->vm_type == J_INT && expr->vm_type == J_DOUBLE) { - state->reg1 = get_var(s->b_parent, J_DOUBLE); + } else { + die("EXPR_CONVERSION_TO_FLOAT: no conversion from %d to %d", src->vm_type, expr->vm_type); + } +} + +freg: EXPR_CONVERSION_TO_DOUBLE(reg) +{ + struct expression *expr, *src; + + expr = to_expr(tree); + src = to_expr(expr->from_expression); + + assert(expr->vm_type == J_DOUBLE); + if (src->vm_type == J_INT) { + state->reg1 = get_var(s->b_parent, J_DOUBLE); select_insn(s, tree, reg_reg_insn(INSN_CONV_GPR_TO_FPU64, state->left->reg1, state->reg1)); } else { die("EXPR_CONVERSION_TO_FLOAT: no conversion from %d to %d", src->vm_type, expr->vm_type); @@ -1465,16 +1502,32 @@ reg: EXPR_CONVERSION_FROM_FLOAT(freg) expr = to_expr(tree); src = to_expr(expr->from_expression); - if (src->vm_type == J_FLOAT && expr->vm_type == J_INT) { + assert(src->vm_type == J_FLOAT); + + if (expr->vm_type == J_INT) { state->reg1 = get_var(s->b_parent, J_INT); select_insn(s, tree, reg_reg_insn(INSN_CONV_FPU_TO_GPR, state->left->reg1, state->reg1)); - } else if (src->vm_type == J_DOUBLE && expr->vm_type == J_INT) { + } else { + die("EXPR_CONVERSION_FROM_FLOAT: no conversion from %d to %d", src->vm_type, expr->vm_type); + } +} + +reg: EXPR_CONVERSION_FROM_DOUBLE(freg) +{ + struct expression *expr, *src; + + expr = to_expr(tree); + src = to_expr(expr->from_expression); + + assert(src->vm_type == J_DOUBLE); + + if (expr->vm_type == J_INT) { state->reg1 = get_var(s->b_parent, J_INT); select_insn(s, tree, reg_reg_insn(INSN_CONV_FPU64_TO_GPR, state->left->reg1, state->reg1)); } else { - die("EXPR_CONVERSION_FROM_FLOAT: no conversion from %d to %d", src->vm_type, expr->vm_type); + die("EXPR_CONVERSION_FROM_DOUBLE: no conversion from %d to %d", src->vm_type, expr->vm_type); } } diff --git a/arch/x86/lir-printer.c b/arch/x86/lir-printer.c index 27f67fa..c0a3600 100644 --- a/arch/x86/lir-printer.c +++ b/arch/x86/lir-printer.c @@ -432,6 +432,18 @@ static int print_conv_gpr_to_fpu64(struct string *str, struct insn *insn) return print_reg_reg(str, insn); } +static int print_conv_xmm_to_xmm64(struct string *str, struct insn *insn) +{ + print_func_name(str); + return print_reg_reg(str, insn); +} + +static int print_conv_xmm64_to_xmm(struct string *str, struct insn *insn) +{ + print_func_name(str); + return print_reg_reg(str, insn); +} + static int print_je_branch(struct string *str, struct insn *insn) { print_func_name(str); @@ -887,6 +899,8 @@ static print_insn_fn insn_printers[] = { [INSN_CONV_FPU64_TO_GPR] = print_conv_fpu64_to_gpr, [INSN_CONV_GPR_TO_FPU] = print_conv_gpr_to_fpu, [INSN_CONV_GPR_TO_FPU64] = print_conv_gpr_to_fpu64, + [INSN_CONV_XMM_TO_XMM64] = print_conv_xmm_to_xmm64, + [INSN_CONV_XMM64_TO_XMM] = print_conv_xmm64_to_xmm, [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 65f6a7a..643b073 100644 --- a/arch/x86/use-def.c +++ b/arch/x86/use-def.c @@ -73,6 +73,8 @@ static struct insn_info insn_infos[] = { DECLARE_INFO(INSN_CONV_GPR_TO_FPU64, USE_SRC | DEF_DST), DECLARE_INFO(INSN_CONV_FPU_TO_GPR, USE_SRC | DEF_DST), DECLARE_INFO(INSN_CONV_FPU64_TO_GPR, USE_SRC | DEF_DST), + DECLARE_INFO(INSN_CONV_XMM_TO_XMM64, USE_SRC | DEF_DST), + DECLARE_INFO(INSN_CONV_XMM64_TO_XMM, USE_SRC | DEF_DST), DECLARE_INFO(INSN_MOV_MEMBASE_XMM, USE_SRC | DEF_DST), DECLARE_INFO(INSN_MOV_64_MEMBASE_XMM, USE_SRC | DEF_DST), DECLARE_INFO(INSN_MOV_XMM_MEMBASE, USE_SRC | USE_DST), diff --git a/include/jit/expression.h b/include/jit/expression.h index 70a459b..e97a7c8 100644 --- a/include/jit/expression.h +++ b/include/jit/expression.h @@ -27,8 +27,12 @@ enum expression_type { EXPR_BINOP, EXPR_UNARY_OP, EXPR_CONVERSION, + EXPR_CONVERSION_FLOAT_TO_DOUBLE, + EXPR_CONVERSION_DOUBLE_TO_FLOAT, EXPR_CONVERSION_FROM_FLOAT, EXPR_CONVERSION_TO_FLOAT, + EXPR_CONVERSION_FROM_DOUBLE, + EXPR_CONVERSION_TO_DOUBLE, EXPR_CLASS_FIELD, EXPR_INSTANCE_FIELD, EXPR_INVOKE, @@ -323,8 +327,13 @@ struct expression *array_deref_expr(enum vm_type, struct expression *, struct ex struct expression *binop_expr(enum vm_type, enum binary_operator, struct expression *, struct expression *); struct expression *unary_op_expr(enum vm_type, enum unary_operator, struct expression *); struct expression *conversion_expr(enum vm_type, struct expression *); +struct expression *conversion_double_to_float_expr(struct expression *); +struct expression *conversion_float_to_double_expr(struct expression *); struct expression *conversion_from_float_expr(enum vm_type, struct expression *); struct expression *conversion_to_float_expr(enum vm_type, struct expression *); +struct expression *conversion_from_double_expr(enum vm_type, struct expression *); +struct expression *conversion_to_double_expr(enum vm_type, struct expression *); + struct expression *class_field_expr(enum vm_type, struct vm_field *); struct expression *instance_field_expr(enum vm_type, struct vm_field *, struct expression *); struct expression *invoke_expr(struct vm_method *); diff --git a/jit/expression.c b/jit/expression.c index 302316f..a2ddd97 100644 --- a/jit/expression.c +++ b/jit/expression.c @@ -42,8 +42,12 @@ int expr_nr_kids(struct expression *expr) return 2; case EXPR_UNARY_OP: case EXPR_CONVERSION: + case EXPR_CONVERSION_FLOAT_TO_DOUBLE: + case EXPR_CONVERSION_DOUBLE_TO_FLOAT: case EXPR_CONVERSION_TO_FLOAT: case EXPR_CONVERSION_FROM_FLOAT: + case EXPR_CONVERSION_TO_DOUBLE: + case EXPR_CONVERSION_FROM_DOUBLE: case EXPR_INSTANCE_FIELD: case EXPR_FLOAT_INSTANCE_FIELD: case EXPR_INVOKE: @@ -99,8 +103,12 @@ int expr_is_pure(struct expression *expr) case EXPR_ARGS_LIST: case EXPR_UNARY_OP: case EXPR_CONVERSION: + case EXPR_CONVERSION_FLOAT_TO_DOUBLE: + case EXPR_CONVERSION_DOUBLE_TO_FLOAT: case EXPR_CONVERSION_TO_FLOAT: case EXPR_CONVERSION_FROM_FLOAT: + case EXPR_CONVERSION_TO_DOUBLE: + case EXPR_CONVERSION_FROM_DOUBLE: case EXPR_ARG: case EXPR_ARG_THIS: case EXPR_ARRAYLENGTH: @@ -310,6 +318,28 @@ struct expression *conversion_expr(enum vm_type vm_type, return expr; } +struct expression * +conversion_double_to_float_expr(struct expression *from_expression) +{ + struct expression *expr; + + expr = alloc_expression(EXPR_CONVERSION_DOUBLE_TO_FLOAT, J_FLOAT); + if (expr) + expr->from_expression = &from_expression->node; + return expr; +} + +struct expression * +conversion_float_to_double_expr(struct expression *from_expression) +{ + struct expression *expr; + + expr = alloc_expression(EXPR_CONVERSION_FLOAT_TO_DOUBLE, J_DOUBLE); + if (expr) + expr->from_expression = &from_expression->node; + return expr; +} + struct expression *conversion_to_float_expr(enum vm_type vm_type, struct expression *from_expression) { @@ -328,6 +358,25 @@ struct expression *conversion_from_float_expr(enum vm_type vm_type, return expr; } +struct expression *conversion_to_double_expr(enum vm_type vm_type, + struct expression *from_expression) +{ + struct expression *expr = alloc_expression(EXPR_CONVERSION_TO_DOUBLE, vm_type); + if (expr) + expr->from_expression = &from_expression->node; + return expr; +} + +struct expression *conversion_from_double_expr(enum vm_type vm_type, + struct expression *from_expression) +{ + struct expression *expr = alloc_expression(EXPR_CONVERSION_FROM_DOUBLE, + vm_type); + if (expr) + expr->from_expression = &from_expression->node; + return expr; +} + struct expression *class_field_expr(enum vm_type vm_type, struct vm_field *class_field) { struct expression *expr; diff --git a/jit/tree-printer.c b/jit/tree-printer.c index 8b1b0fe..e9ede43 100644 --- a/jit/tree-printer.c +++ b/jit/tree-printer.c @@ -1014,8 +1014,12 @@ static print_expr_fn expr_printers[] = { [EXPR_BINOP] = print_binop_expr, [EXPR_UNARY_OP] = print_unary_op_expr, [EXPR_CONVERSION] = print_conversion_expr, + [EXPR_CONVERSION_FLOAT_TO_DOUBLE] = print_conversion_expr, + [EXPR_CONVERSION_DOUBLE_TO_FLOAT] = print_conversion_expr, [EXPR_CONVERSION_FROM_FLOAT] = print_conversion_expr, [EXPR_CONVERSION_TO_FLOAT] = print_conversion_expr, + [EXPR_CONVERSION_FROM_DOUBLE] = print_conversion_expr, + [EXPR_CONVERSION_TO_DOUBLE] = print_conversion_expr, [EXPR_CLASS_FIELD] = print_class_field_expr, [EXPR_FLOAT_CLASS_FIELD] = print_float_class_field_expr, [EXPR_INSTANCE_FIELD] = print_instance_field_expr, diff --git a/jit/typeconv-bc.c b/jit/typeconv-bc.c index ca3300f..3a3b0e7 100644 --- a/jit/typeconv-bc.c +++ b/jit/typeconv-bc.c @@ -21,13 +21,23 @@ static int convert_conversion(struct parse_context *ctx, enum vm_type to_type) { struct expression *from_expression, *conversion_expression; + enum vm_type from_type; from_expression = stack_pop(ctx->bb->mimic_stack); + from_type = from_expression->vm_type; - if (vm_type_is_float(to_type)) + if (from_type == J_DOUBLE && to_type == J_FLOAT) + conversion_expression = conversion_double_to_float_expr(from_expression); + else if (from_type == J_FLOAT && to_type == J_DOUBLE) + conversion_expression = conversion_float_to_double_expr(from_expression); + else if (to_type == J_FLOAT) conversion_expression = conversion_to_float_expr(to_type, from_expression); - else if (vm_type_is_float(from_expression->vm_type)) + else if (from_type == J_FLOAT) conversion_expression = conversion_from_float_expr(to_type, from_expression); + else if (to_type == J_DOUBLE) + conversion_expression = conversion_to_double_expr(to_type, from_expression); + else if (from_type == J_DOUBLE) + conversion_expression = conversion_from_double_expr(to_type, from_expression); else conversion_expression = conversion_expr(to_type, from_expression); diff --git a/test/jit/typeconv-bc-test.c b/test/jit/typeconv-bc-test.c index f409f4d..77bac3a 100644 --- a/test/jit/typeconv-bc-test.c +++ b/test/jit/typeconv-bc-test.c @@ -42,28 +42,28 @@ void test_convert_int_widening(void) { assert_conversion_mimic_stack(OPC_I2L, EXPR_CONVERSION, J_INT, J_LONG); assert_conversion_mimic_stack(OPC_I2F, EXPR_CONVERSION_TO_FLOAT, J_INT, J_FLOAT); - assert_conversion_mimic_stack(OPC_I2D, EXPR_CONVERSION, J_INT, J_DOUBLE); + assert_conversion_mimic_stack(OPC_I2D, EXPR_CONVERSION_TO_DOUBLE, J_INT, J_DOUBLE); } void test_convert_long_conversion(void) { assert_conversion_mimic_stack(OPC_L2I, EXPR_CONVERSION, J_LONG, J_INT); assert_conversion_mimic_stack(OPC_L2F, EXPR_CONVERSION_TO_FLOAT, J_LONG, J_FLOAT); - assert_conversion_mimic_stack(OPC_L2D, EXPR_CONVERSION, J_LONG, J_DOUBLE); + assert_conversion_mimic_stack(OPC_L2D, EXPR_CONVERSION_TO_DOUBLE, J_LONG, J_DOUBLE); } void test_convert_float_conversion(void) { assert_conversion_mimic_stack(OPC_F2I, EXPR_CONVERSION_FROM_FLOAT, J_FLOAT, J_INT); assert_conversion_mimic_stack(OPC_F2L, EXPR_CONVERSION_FROM_FLOAT, J_FLOAT, J_LONG); - assert_conversion_mimic_stack(OPC_F2D, EXPR_CONVERSION_FROM_FLOAT, J_FLOAT, J_DOUBLE); + assert_conversion_mimic_stack(OPC_F2D, EXPR_CONVERSION_FLOAT_TO_DOUBLE, J_FLOAT, J_DOUBLE); } void test_convert_double_conversion(void) { - assert_conversion_mimic_stack(OPC_D2I, EXPR_CONVERSION, J_DOUBLE, J_INT); - assert_conversion_mimic_stack(OPC_D2L, EXPR_CONVERSION, J_DOUBLE, J_LONG); - assert_conversion_mimic_stack(OPC_D2F, EXPR_CONVERSION_TO_FLOAT, J_DOUBLE, J_FLOAT); + assert_conversion_mimic_stack(OPC_D2I, EXPR_CONVERSION_FROM_DOUBLE, J_DOUBLE, J_INT); + assert_conversion_mimic_stack(OPC_D2L, EXPR_CONVERSION_FROM_DOUBLE, J_DOUBLE, J_LONG); + assert_conversion_mimic_stack(OPC_D2F, EXPR_CONVERSION_DOUBLE_TO_FLOAT, J_DOUBLE, J_FLOAT); } void test_convert_int_narrowing(void) -- 1.6.0.6 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel