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