Signed-off-by: Tomek Grabiec <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel