This instruction saves the address of itself to a memory location
with GS segment override prefix. It will be needed for storing the
approximate call site address into JNI call stack entry.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/emit-code.c                |   35 ++++++++++++++++++++++++++++++---
 arch/x86/include/arch/instruction.h |    1 +
 arch/x86/lir-printer.c              |   36 ++++++++++++++++++++++++++--------
 arch/x86/use-def.c                  |    1 +
 4 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index f3a0485..53ef166 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -477,6 +477,8 @@ static void emit_mov_reg_membase(struct buffer *buf, struct 
operand *src,
                                 struct operand *dest);
 static void emit_mov_imm_membase(struct buffer *buf, struct operand *src,
                                 struct operand *dest);
+static void __emit_mov_imm_membase(struct buffer *buf, long imm,
+                                  enum machine_reg base, long disp);
 
 /*
  *     __encode_reg:   Encode register to be used in IA-32 instruction.
@@ -753,6 +755,16 @@ static void emit_mov_imm_thread_local_membase(struct 
buffer *buf,
        emit_mov_imm_membase(buf, src, dest);
 }
 
+static void emit_mov_ip_thread_local_membase(struct buffer *buf,
+                                            struct operand *dest)
+{
+       unsigned long addr
+               = (unsigned long)buffer_current(buf);
+
+       emit(buf, 0x65); /* GS segment override prefix */
+       __emit_mov_imm_membase(buf, addr, mach_reg(&dest->base_reg), 
dest->disp);
+}
+
 static void emit_mov_memdisp_reg(struct buffer *buf,
                                 struct operand *src,
                                 struct operand *dest)
@@ -787,18 +799,32 @@ static void emit_mov_imm_reg(struct buffer *buf, struct 
operand *src,
        __emit_mov_imm_reg(buf, src->imm, mach_reg(&dest->reg));
 }
 
+static void __emit_mov_imm_membase(struct buffer *buf, long imm,
+                                  enum machine_reg base, long disp)
+{
+       __emit_membase(buf, 0xc7, base, disp, 0);
+       emit_imm32(buf, imm);
+}
+
 static void emit_mov_imm_membase(struct buffer *buf, struct operand *src,
                                 struct operand *dest)
 {
-       __emit_membase(buf, 0xc7, mach_reg(&dest->base_reg), dest->disp, 0);
+       __emit_mov_imm_membase(buf, src->imm, mach_reg(&dest->base_reg),
+                              dest->disp);
+}
 
-       emit_imm32(buf, src->imm);
+static void __emit_mov_reg_membase(struct buffer *buf, enum machine_reg src,
+                                  enum machine_reg base, unsigned long disp)
+{
+       __emit_membase(buf, 0x89, base, disp, __encode_reg(src));
 }
 
 static void
-emit_mov_reg_membase(struct buffer *buf, struct operand *src, struct operand 
*dest)
+emit_mov_reg_membase(struct buffer *buf, struct operand *src,
+                    struct operand *dest)
 {
-       __emit_membase(buf, 0x89, mach_reg(&dest->base_reg), dest->disp, 
encode_reg(&src->reg));
+       __emit_mov_reg_membase(buf, mach_reg(&src->reg),
+                              mach_reg(&dest->base_reg), dest->disp);
 }
 
 static void emit_mov_reg_memlocal(struct buffer *buf, struct operand *src,
@@ -1344,6 +1370,7 @@ struct emitter emitters[] = {
        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_IMM_THREAD_LOCAL_MEMBASE, 
emit_mov_imm_thread_local_membase, TWO_OPERANDS),
+       DECL_EMITTER(INSN_MOV_IP_THREAD_LOCAL_MEMBASE, 
emit_mov_ip_thread_local_membase, SINGLE_OPERAND),
        DECL_EMITTER(INSN_MOV_MEMLOCAL_REG, emit_mov_memlocal_reg, 
TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_MEMLOCAL_FREG, emit_mov_memlocal_freg, 
TWO_OPERANDS),
        DECL_EMITTER(INSN_MOV_MEMBASE_REG, emit_mov_membase_reg, TWO_OPERANDS),
diff --git a/arch/x86/include/arch/instruction.h 
b/arch/x86/include/arch/instruction.h
index a5bd8da..a0657e9 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_THREAD_LOCAL_MEMBASE,
        INSN_MOV_MEMLOCAL_REG,
        INSN_MOV_MEMLOCAL_FREG,
        INSN_MOV_MEMBASE_REG,
diff --git a/arch/x86/lir-printer.c b/arch/x86/lir-printer.c
index 208fd28..7d7d7ad 100644
--- a/arch/x86/lir-printer.c
+++ b/arch/x86/lir-printer.c
@@ -133,28 +133,39 @@ static int print_tlmemdisp_reg(struct string *str, struct 
insn *insn)
        return print_reg(str, &insn->dest);
 }
 
+static int print_tlmembase(struct string *str, struct operand *op)
+{
+       str_append(str, "gs:(");
+       print_membase(str, op);
+       return str_append(str, ")");
+}
+
+static int print_tlmemdisp(struct string *str, struct operand *op)
+{
+       str_append(str, "gs:(");
+       print_imm(str, op);
+       return str_append(str, ")");
+}
+
 static int print_reg_tlmemdisp(struct string *str, struct insn *insn)
 {
        print_reg(str, &insn->src);
-       str_append(str, ", gs:(");
-       print_imm(str, &insn->dest);
-       return str_append(str, ")");
+       str_append(str, ", ");
+       return print_tlmemdisp(str, &insn->dest);
 }
 
 static int print_imm_tlmembase(struct string *str, struct insn *insn)
 {
        print_imm(str, &insn->src);
-       str_append(str, ", gs:(");
-       print_membase(str, &insn->dest);
-       return str_append(str, ")");
+       str_append(str, ", ");
+       return print_tlmembase(str, &insn->dest);
 }
 
 static int print_reg_tlmembase(struct string *str, struct insn *insn)
 {
        print_reg(str, &insn->src);
-       str_append(str, ", gs:(");
-       print_membase(str, &insn->dest);
-       return str_append(str, ")");
+       str_append(str, ", ");
+       return print_tlmembase(str, &insn->dest);
 }
 
 static int print_reg_membase(struct string *str, struct insn *insn)
@@ -461,6 +472,12 @@ static int print_mov_imm_tlmembase(struct string *str, 
struct insn *insn)
        return print_imm_tlmembase(str, insn);
 }
 
+static int print_mov_ip_tlmembase(struct string *str, struct insn *insn)
+{
+       print_func_name(str);
+       return print_tlmembase(str, &insn->operands[0]);
+}
+
 static int print_mov_reg_tlmembase(struct string *str, struct insn *insn)
 {
        print_func_name(str);
@@ -711,6 +728,7 @@ static print_insn_fn insn_printers[] = {
        [INSN_MOV_IMM_MEMBASE] = print_mov_imm_membase,
        [INSN_MOV_IMM_REG] = print_mov_imm_reg,
        [INSN_MOV_IMM_THREAD_LOCAL_MEMBASE] = print_mov_imm_tlmembase,
+       [INSN_MOV_IP_THREAD_LOCAL_MEMBASE] = print_mov_ip_tlmembase,
        [INSN_MOV_MEMLOCAL_REG] = print_mov_memlocal_reg,
        [INSN_MOV_MEMLOCAL_FREG] = print_mov_memlocal_freg,
        [INSN_MOV_MEMBASE_REG] = print_mov_membase_reg,
diff --git a/arch/x86/use-def.c b/arch/x86/use-def.c
index 3a140d0..652314d 100644
--- a/arch/x86/use-def.c
+++ b/arch/x86/use-def.c
@@ -75,6 +75,7 @@ static struct insn_info insn_infos[] = {
        DECLARE_INFO(INSN_MOV_IMM_MEMBASE, USE_DST),
        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_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