There's no 64-bit operand size imm->membase move instruction on x86-64.
Therefore, we first do an imm->reg move, then a reg->membase move.

Signed-off-by: Eduard - Gabriel Munteanu <eduard.munte...@linux360.ro>
---
 arch/x86/emit-code.c                |    8 +++
 arch/x86/include/arch/instruction.h |    1 +
 arch/x86/insn-selector.brg          |   95 ++++++++++++++++++++++++++++++++---
 arch/x86/use-def.c                  |    1 +
 4 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index 47bd429..5b3ab70 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -2180,6 +2180,13 @@ static void emit_mov_imm_reg(struct buffer *buf,
        __emit64_mov_imm_reg(buf, src->imm, mach_reg(&dest->reg));
 }
 
+static void emit_mov_ip_reg(struct buffer *buf, struct operand *dest)
+{
+       long addr = (long) buffer_current(buf);
+
+       __emit64_mov_imm_reg(buf, addr, mach_reg(&dest->reg));
+}
+
 static void __emit64_mov_membase_reg(struct buffer *buf,
                                     enum machine_reg base_reg,
                                     unsigned long disp,
@@ -2275,6 +2282,7 @@ struct emitter emitters[] = {
        DECL_EMITTER(INSN_CMP_MEMBASE_REG, emit_cmp_membase_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_CMP_REG_REG, emit_cmp_reg_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_IMM_REG, emit_mov_imm_reg, TWO_OPERANDS),
+       DECL_EMITTER(INSN_MOV_IP_REG, emit_mov_ip_reg, SINGLE_OPERAND),
        DECL_EMITTER(INSN_MOV_MEMBASE_REG, emit_mov_membase_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_MEMDISP_REG, emit_mov_memdisp_reg, TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_MEMLOCAL_REG, emit_mov_memlocal_reg, 
TWO_OPERANDS),
diff --git a/arch/x86/include/arch/instruction.h 
b/arch/x86/include/arch/instruction.h
index 2381ba6..a346145 100644
--- a/arch/x86/include/arch/instruction.h
+++ b/arch/x86/include/arch/instruction.h
@@ -88,6 +88,7 @@ enum insn_type {
        INSN_MOV_IMM_MEMBASE,
        INSN_MOV_IMM_REG,
        INSN_MOV_IMM_THREAD_LOCAL_MEMBASE,
+       INSN_MOV_IP_REG,
        INSN_MOV_IP_THREAD_LOCAL_MEMBASE,
        INSN_MOV_MEMLOCAL_REG,
        INSN_MOV_MEMLOCAL_FREG,
diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index 5ef161c..bf8695f 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -2031,6 +2031,61 @@ emulate_op_64(struct _MBState *state, struct basic_block 
*s,
                select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx, 
state->reg2));
 }
 
+#ifdef CONFIG_X86_32
+static void select_jni_set_call_site_addr(struct basic_block *s,
+                                         struct tree_node *tree,
+                                         struct var_info *offset_reg,
+                                         unsigned long field)
+{
+       select_insn(s, tree,
+                   membase_insn(INSN_MOV_IP_THREAD_LOCAL_MEMBASE,
+                                offset_reg, field));
+}
+
+static void select_jni_set_method(struct basic_block *s,
+                                 struct tree_node *tree,
+                                 struct vm_method *method,
+                                 struct var_info *offset_reg,
+                                 unsigned long field)
+{
+       select_insn(s, tree, imm_membase_insn(INSN_MOV_IMM_THREAD_LOCAL_MEMBASE,
+                               (unsigned long) method, offset_reg, field));
+}
+#else /* CONFIG_X86_32 */
+static void select_jni_set_call_site_addr(struct basic_block *s,
+                                         struct tree_node *tree,
+                                         struct var_info *offset_reg,
+                                         unsigned long field)
+{
+       struct var_info *ip_reg;
+
+       ip_reg = get_var(s->b_parent, J_LONG);
+
+       select_insn(s, tree, reg_insn(INSN_MOV_IP_REG, ip_reg));
+       select_insn(s, tree,
+                   reg_membase_insn(INSN_MOV_REG_THREAD_LOCAL_MEMBASE,
+                                    ip_reg, offset_reg, field));
+}
+
+static void select_jni_set_method(struct basic_block *s,
+                                 struct tree_node *tree,
+                                 struct vm_method *method,
+                                 struct var_info *offset_reg,
+                                 unsigned long field)
+{
+       struct var_info *method_reg;
+
+       method_reg = get_var(s->b_parent, J_LONG);
+
+       select_insn(s, tree,
+                   imm_reg_insn(INSN_MOV_IMM_REG,
+                                (unsigned long) method, method_reg));
+       select_insn(s, tree,
+                   reg_membase_insn(INSN_MOV_REG_THREAD_LOCAL_MEMBASE,
+                                    method_reg, offset_reg, field));
+}
+#endif /* CONFIG_X86_32 */
+
 static void select_jni_call(struct basic_block *s, struct tree_node *tree,
                            struct insn *call_insn, struct vm_method *method)
 {
@@ -2073,14 +2128,11 @@ static void select_jni_call(struct basic_block *s, 
struct tree_node *tree,
 
        /* Set ->call_site_addr */
        field = tr_addr + offsetof(struct jni_stack_entry, call_site_addr);
-       select_insn(s, tree,
-                   membase_insn(INSN_MOV_IP_THREAD_LOCAL_MEMBASE,
-                                offset_reg, field));
+       select_jni_set_call_site_addr(s, tree, offset_reg, field);
 
        /* Set ->method */
        field = tr_addr + offsetof(struct jni_stack_entry, method);
-       select_insn(s, tree, imm_membase_insn(INSN_MOV_IMM_THREAD_LOCAL_MEMBASE,
-                               (unsigned long) method, offset_reg, field));
+       select_jni_set_method(s, tree, method, offset_reg, field);
 
        select_insn(s, tree, call_insn);
 
@@ -2093,6 +2145,36 @@ static void select_jni_call(struct basic_block *s, 
struct tree_node *tree,
                                     offset_reg, offset_tls));
 }
 
+#ifdef CONFIG_X86_32
+static void select_set_target(struct basic_block *s,
+                             struct tree_node *tree,
+                             void *target,
+                             struct var_info *offset_reg,
+                             unsigned long field)
+{
+       select_insn(s, tree, imm_membase_insn(INSN_MOV_IMM_THREAD_LOCAL_MEMBASE,
+                               (unsigned long) target, offset_reg, field));
+}
+#else
+static void select_set_target(struct basic_block *s,
+                             struct tree_node *tree,
+                             void *target,
+                             struct var_info *offset_reg,
+                             unsigned long field)
+{
+       struct var_info *target_reg;
+
+       target_reg = get_var(s->b_parent, J_LONG);
+
+       select_insn(s, tree,
+                   imm_reg_insn(INSN_MOV_IMM_REG,
+                                (unsigned long) target, target_reg));
+       select_insn(s, tree,
+                   reg_membase_insn(INSN_MOV_REG_THREAD_LOCAL_MEMBASE,
+                                    target_reg, offset_reg, field));
+}
+#endif
+
 static void select_vm_native_call(struct basic_block *s, struct tree_node 
*tree,
                                  struct insn *call_insn, void *target)
 {
@@ -2134,8 +2216,7 @@ static void select_vm_native_call(struct basic_block *s, 
struct tree_node *tree,
 
        /* Set ->target */
        field = tr_addr + offsetof(struct vm_native_stack_entry, target);
-       select_insn(s, tree, imm_membase_insn(INSN_MOV_IMM_THREAD_LOCAL_MEMBASE,
-                               (unsigned long) target, offset_reg, field));
+       select_set_target(s, tree, target, offset_reg, field);
 
        select_insn(s, tree, call_insn);
 
diff --git a/arch/x86/use-def.c b/arch/x86/use-def.c
index b09add2..93bb561 100644
--- a/arch/x86/use-def.c
+++ b/arch/x86/use-def.c
@@ -76,6 +76,7 @@ static struct insn_info insn_infos[] = {
        DECLARE_INFO(INSN_MOV_IMM_REG, DEF_DST),
        DECLARE_INFO(INSN_MOV_IMM_THREAD_LOCAL_MEMBASE, USE_NONE | DEF_NONE),
        DECLARE_INFO(INSN_MOV_IP_THREAD_LOCAL_MEMBASE, USE_NONE | DEF_NONE),
+       DECLARE_INFO(INSN_MOV_IP_REG, DEF_DST),
        DECLARE_INFO(INSN_MOV_MEMLOCAL_REG, USE_FP | DEF_DST),
        DECLARE_INFO(INSN_MOV_MEMLOCAL_FREG, USE_FP | DEF_DST),
        DECLARE_INFO(INSN_MOV_MEMBASE_REG, USE_SRC | DEF_DST),
-- 
1.6.0.6


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

Reply via email to