aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2012-01-14 12:54:39 +0200
committerPekka Enberg <penberg@kernel.org>2012-01-14 12:57:15 +0200
commit00ec60f2828bfcb765f96c5075d9ceb9ca8a0023 (patch)
tree88e38d7a53778cdf54b50c632a07e493e2bcb80a
parent0ab0e6fa38af8acb500e7c0e75b386a68ad4771a (diff)
downloadjato-00ec60f2828bfcb765f96c5075d9ceb9ca8a0023.tar.gz
x86-32: Remove 64-bit ifdefs from emit_32.c
Same as commit 27dcbf7 ("x86-64: Remove 32-bit ifdefs from emit_64.c") but for 32-bit. Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--arch/x86/emit_32.c1210
1 files changed, 0 insertions, 1210 deletions
diff --git a/arch/x86/emit_32.c b/arch/x86/emit_32.c
index 9cbd2913..d2e2dff9 100644
--- a/arch/x86/emit_32.c
+++ b/arch/x86/emit_32.c
@@ -77,13 +77,7 @@ static void __emit_mov_reg_reg(struct buffer *buf, enum machine_reg src, enum ma
static void emit_indirect_jump_reg(struct buffer *buf, enum machine_reg reg);
static void emit_exception_test(struct buffer *buf, enum machine_reg reg);
static void emit_restore_regs(struct buffer *buf);
-
-#ifdef CONFIG_X86_32
static void __emit_push_membase(struct buffer *buf, enum machine_reg src_reg, unsigned long disp);
-#else
-static void emit_save_regparm(struct buffer *buf);
-static void emit_restore_regparm(struct buffer *buf);
-#endif
/*
* Common code emitters
@@ -191,10 +185,6 @@ static void __emit_push_reg(struct buffer *buf, enum machine_reg reg)
rm = x86_encode_reg(reg);
-#ifdef CONFIG_X86_64
- if (reg_high(rm))
- rex_pfx |= REX_B;
-#endif
if (rex_pfx)
emit(buf, rex_pfx);
@@ -207,10 +197,6 @@ static void __emit_pop_reg(struct buffer *buf, enum machine_reg reg)
rm = x86_encode_reg(reg);
-#ifdef CONFIG_X86_64
- if (reg_high(rm))
- rex_pfx |= REX_B;
-#endif
if (rex_pfx)
emit(buf, rex_pfx);
@@ -344,21 +330,12 @@ static void __emit_jmp(struct buffer *buf, unsigned long addr)
* FIXME: We use different stack layout on 32-bit and 64-bit so prolog, epilog,
* and unwind sequences are slightly different.
*/
-#ifdef CONFIG_X86_32
void emit_unwind(struct buffer *buf)
{
emit_leave(buf);
emit_restore_regs(buf);
__emit_jmp(buf, (unsigned long)&unwind);
}
-#else
-void emit_unwind(struct buffer *buf)
-{
- emit_restore_regs(buf);
- emit_leave(buf);
- __emit_jmp(buf, (unsigned long)&unwind);
-}
-#endif
static void __emit_mov_imm_reg(struct buffer *buf, long imm, enum machine_reg reg)
{
@@ -366,24 +343,12 @@ static void __emit_mov_imm_reg(struct buffer *buf, long imm, enum machine_reg re
emit_imm32(buf, imm);
}
-#ifdef CONFIG_X86_32
void emit_trace_invoke(struct buffer *buf, struct compilation_unit *cu)
{
__emit_push_imm(buf, (unsigned long) cu);
__emit_call(buf, &trace_invoke);
__emit_add_imm_reg(buf, PTR_SIZE, MACH_REG_xSP);
}
-#else /* CONFIG_X86_64 */
-void emit_trace_invoke(struct buffer *buf, struct compilation_unit *cu)
-{
- emit_save_regparm(buf);
-
- __emit_mov_imm_reg(buf, (unsigned long) cu, MACH_REG_RDI);
- __emit_call(buf, &trace_invoke);
-
- emit_restore_regparm(buf);
-}
-#endif
static void fixup_branch_target(uint8_t *target_p, void *target)
{
@@ -400,13 +365,6 @@ static void emit_really_indirect_jump_reg(struct buffer *buf, enum machine_reg r
emit(buf, x86_encode_mod_rm(0x0, 0x04, x86_encode_reg(reg)));
}
-
-#ifdef CONFIG_X86_32
-
-/*
- * x86-32 code emitters
- */
-
static void emit_mov_reg_membase(struct insn *insn, struct buffer *buf, struct basic_block *bb);
static void emit_mov_imm_membase(struct insn *insn, struct buffer *buf, struct basic_block *bb);
@@ -1073,1142 +1031,6 @@ void emit_ic_miss_handler(struct buffer *buf, void *ic_check, struct vm_method *
emit_indirect_jump_reg(buf, MACH_REG_EAX);
}
-
-#else /* CONFIG_X86_32 */
-
-/*
- * x86-64 code emitters
- */
-
-static inline void emit_str(struct buffer *buf, unsigned char *str, size_t len)
-{
- int err;
-
- err = append_buffer_str(buf, str, len);
- assert(!err);
-}
-
-static int has_legacy_prefix(unsigned char *str, size_t len)
-{
- if (len <= 1)
- return 0;
-
- switch (str[0]) {
- case 0xF2:
- case 0xF3:
- return 1;
- default:
- return 0;
- }
-}
-
-static void emit_lopc(struct buffer *buf, int rex, unsigned char *str, size_t len)
-{
- if (rex && has_legacy_prefix(str, len)) {
- emit(buf, str[0]);
- emit(buf, rex);
- emit_str(buf, str + 1, len - 1);
- } else {
- if (rex)
- emit(buf, rex);
- emit_str(buf, str, len);
- }
-}
-
-static inline unsigned long rip_relative(struct buffer *buf,
- unsigned long addr,
- unsigned long insn_size)
-{
- return addr - (unsigned long) buffer_current(buf) - insn_size;
-}
-
-static inline int is_64bit_reg(struct operand *reg)
-{
- switch (reg->reg.interval->var_info->vm_type) {
- case J_LONG:
- case J_REFERENCE:
- case J_DOUBLE:
- return 1;
- default:
- return 0;
- }
-}
-
-static int is_64bit_bin_reg_op(struct operand *a, struct operand *b)
-{
- return is_64bit_reg(a) || is_64bit_reg(b);
-}
-
-static void __emit_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg reg)
-{
- unsigned char reg_num = x86_encode_reg(reg);
- unsigned char rex_pfx = 0;
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(reg_num))
- rex_pfx |= REX_B;
-
- if (rex_pfx)
- emit(buf, rex_pfx);
- emit(buf, opc + reg_low(reg_num));
-}
-
-static void __emit_lopc_reg_reg(struct buffer *buf,
- int rex_w,
- unsigned char *lopc,
- size_t lopc_size,
- enum machine_reg direct_reg,
- enum machine_reg rm_reg)
-{
- unsigned char rex_pfx = 0, mod_rm;
- unsigned char direct, rm;
-
- direct = x86_encode_reg(direct_reg);
- rm = x86_encode_reg(rm_reg);
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(direct))
- rex_pfx |= REX_R;
- if (reg_high(rm))
- rex_pfx |= REX_B;
-
- mod_rm = x86_encode_mod_rm(0x03, direct, rm);
-
- emit_lopc(buf, rex_pfx, lopc, lopc_size);
- emit(buf, mod_rm);
-}
-
-static inline void __emit_reg_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg direct_reg,
- enum machine_reg rm_reg)
-{
- __emit_lopc_reg_reg(buf, rex_w, &opc, 1, direct_reg, rm_reg);
-}
-
-static void emit_reg_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- struct operand *direct,
- struct operand *rm)
-{
- enum machine_reg direct_reg, rm_reg;
-
- direct_reg = mach_reg(&direct->reg);
- rm_reg = mach_reg(&rm->reg);
-
- __emit_reg_reg(buf, rex_w, opc, direct_reg, rm_reg);
-}
-
-static void __emit_mov_reg_reg(struct buffer *buf,
- enum machine_reg src,
- enum machine_reg dst)
-{
- __emit_reg_reg(buf, 1, 0x89, src, dst);
-}
-
-static void emit_mul_gpr_gpr(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- unsigned char opc[2];
- int rex_w = is_64bit_bin_reg_op(&insn->src, &insn->dest);
-
- opc[0] = 0x0F;
- opc[1] = 0xAF;
- __emit_lopc_reg_reg(buf, rex_w, opc, 2, mach_reg(&insn->dest.reg), mach_reg(&insn->src.reg));
-}
-
-static void emit_mul_xmm_xmm(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- unsigned char opc[3];
- enum machine_reg src, dest;
-
- if (!is_64bit_reg(&insn->src))
- /* MULSS */
- opc[0] = 0xF3;
- else
- /* MULSD */
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x59;
-
- src = mach_reg(&insn->src.reg);
- dest = mach_reg(&insn->dest.reg);
-
- __emit_lopc_reg_reg(buf, 0, opc, 3, dest, src);
-}
-
-static void emit_mul_reg_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int fp;
-
- fp = operand_is_xmm_reg(&insn->src);
- if (fp != operand_is_xmm_reg(&insn->dest))
- assert(!"Can't do 'mul' between XMM and GPR!");
-
- if (fp)
- emit_mul_xmm_xmm(insn, buf, bb);
- else
- emit_mul_gpr_gpr(insn, buf, bb);
-}
-
-static void emit_alu_imm_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc_ext,
- long imm,
- enum machine_reg reg)
-{
- unsigned char rex_pfx = 0, opc, reg_num;
-
- reg_num = x86_encode_reg(reg);
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(reg_num))
- rex_pfx |= REX_B;
-
- if (is_imm_8(imm))
- opc = 0x83;
- else
- opc = 0x81;
-
- if (rex_pfx)
- emit(buf, rex_pfx);
- emit(buf, opc);
- emit(buf, x86_encode_mod_rm(0x3, opc_ext, reg_num));
- emit_imm(buf, imm);
-}
-
-static void __emit64_sub_imm_reg(struct buffer *buf,
- unsigned long imm,
- enum machine_reg reg)
-{
- emit_alu_imm_reg(buf, 1, 0x05, imm, reg);
-}
-
-static void __emit_add_imm_reg(struct buffer *buf,
- long imm,
- enum machine_reg reg)
-{
- emit_alu_imm_reg(buf, 1, 0x00, imm, reg);
-}
-
-#ifdef CONFIG_X86_32
-static void __emit32_add_imm_reg(struct buffer *buf,
- long imm,
- enum machine_reg reg)
-{
- emit_alu_imm_reg(buf, 0, 0x00, imm, reg);
-}
-#endif
-
-static void emit_imm64(struct buffer *buf, unsigned long imm)
-{
- union {
- unsigned long val;
- unsigned char b[8];
- } imm_buf;
-
- imm_buf.val = imm;
- emit(buf, imm_buf.b[0]);
- emit(buf, imm_buf.b[1]);
- emit(buf, imm_buf.b[2]);
- emit(buf, imm_buf.b[3]);
- emit(buf, imm_buf.b[4]);
- emit(buf, imm_buf.b[5]);
- emit(buf, imm_buf.b[6]);
- emit(buf, imm_buf.b[7]);
-}
-
-#ifdef CONFIG_X86_32
-static void emit64_imm(struct buffer *buf, long imm)
-{
- if (is_imm_8(imm))
- emit(buf, imm);
- else
- emit_imm64(buf, imm);
-}
-#endif
-
-static void emit_push_imm(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_push_imm(buf, insn->operand.imm);
-}
-
-static void __emit_lopc_membase(struct buffer *buf,
- int rex_w,
- unsigned char *lopc,
- size_t lopc_size,
- enum machine_reg base_reg,
- unsigned long disp,
- unsigned char reg_opcode)
-{
- unsigned char rex_pfx = 0, mod, rm, mod_rm;
- unsigned char __base_reg = x86_encode_reg(base_reg);
- int needs_sib, needs_disp;
-
- needs_sib = (base_reg == MACH_REG_RSP || base_reg == MACH_REG_R12);
- needs_disp = (disp || base_reg == MACH_REG_R13);
-
- if (needs_sib)
- rm = 0x04;
- else
- rm = __base_reg;
-
- if (!needs_disp)
- mod = 0x00;
- else if (is_imm_8(disp))
- mod = 0x01;
- else
- mod = 0x02;
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(reg_opcode))
- rex_pfx |= REX_R;
- if (reg_high(__base_reg))
- rex_pfx |= REX_B;
-
- emit_lopc(buf, rex_pfx, lopc, lopc_size);
-
- mod_rm = x86_encode_mod_rm(mod, reg_opcode, rm);
- emit(buf, mod_rm);
-
- if (needs_sib)
- emit(buf, x86_encode_sib(0x00, 0x04, __base_reg));
-
- if (needs_disp)
- emit_imm(buf, disp);
-}
-
-static void __emit_membase(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg base_reg,
- unsigned long disp,
- unsigned char reg_opcode)
-{
- __emit_lopc_membase(buf, rex_w, &opc, 1, base_reg, disp, reg_opcode);
-}
-
-static void __emit_lopc_membase_reg(struct buffer *buf,
- int rex_w,
- unsigned char *lopc,
- size_t lopc_size,
- enum machine_reg base_reg,
- unsigned long disp,
- enum machine_reg dest_reg)
-{
- __emit_lopc_membase(buf, rex_w, lopc, lopc_size,
- base_reg, disp, x86_encode_reg(dest_reg));
-}
-
-static void __emit_membase_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg base_reg,
- unsigned long disp,
- enum machine_reg dest_reg)
-{
- __emit_membase(buf, rex_w, opc, base_reg, disp, x86_encode_reg(dest_reg));
-}
-
-static void __emit_lopc_reg_membase(struct buffer *buf,
- int rex_w,
- unsigned char *lopc,
- size_t lopc_size,
- enum machine_reg src_reg,
- enum machine_reg base_reg,
- unsigned long disp)
-{
- __emit_lopc_membase(buf, rex_w, lopc, lopc_size,
- base_reg, disp, x86_encode_reg(src_reg));
-}
-
-static void __emit_reg_membase(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg src_reg,
- enum machine_reg base_reg,
- unsigned long disp)
-{
- __emit_lopc_reg_membase(buf, rex_w, &opc, 1, src_reg, base_reg, disp);
-}
-
-static void emit_membase_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- struct operand *src,
- struct operand *dest)
-{
- enum machine_reg base_reg, dest_reg;
- unsigned long disp;
-
- base_reg = mach_reg(&src->base_reg);
- disp = src->disp;
- dest_reg = mach_reg(&dest->reg);
-
- __emit_membase_reg(buf, rex_w, opc, base_reg, disp, dest_reg);
-}
-
-#ifdef CONFIG_X86_32
-static void emit_reg_membase(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- struct operand *src,
- struct operand *dest)
-{
- enum machine_reg src_reg, base_reg;
- unsigned long disp;
-
- base_reg = mach_reg(&dest->base_reg);
- disp = dest->disp;
- src_reg = mach_reg(&src->reg);
-
- __emit_reg_membase(buf, rex_w, opc, src_reg, base_reg, disp);
-}
-
-static void __emit_push_membase(struct buffer *buf,
- enum machine_reg src_reg,
- unsigned long disp)
-{
- __emit_membase(buf, 0, 0xff, src_reg, disp, 6);
-}
-#endif
-
-static void __emit_mov_reg_membase(struct buffer *buf,
- int rex_w,
- enum machine_reg src,
- enum machine_reg base,
- unsigned long disp)
-{
- __emit_membase(buf, rex_w, 0x89, base, disp, x86_encode_reg(src));
-}
-
-static void emit_mov_gpr_membase(struct insn *insn,
- struct buffer *buf,
- struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->src);
-
- __emit_mov_reg_membase(buf, rex_w, mach_reg(&insn->src.reg),
- mach_reg(&insn->dest.base_reg), insn->dest.disp);
-}
-
-static void emit_mov_xmm_membase(struct insn *insn,
- struct buffer *buf,
- struct basic_block *bb)
-{
- unsigned char opc[3];
- enum machine_reg src, base;
- unsigned long disp;
-
- if (!is_64bit_reg(&insn->src))
- /* MOVSS */
- opc[0] = 0xF3;
- else
- /* MOVSD */
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x11;
-
- src = mach_reg(&insn->src.reg);
- base = mach_reg(&insn->dest.base_reg);
- disp = insn->dest.disp;
-
- __emit_lopc_reg_membase(buf, 0, opc, 3, src, base, disp);
-}
-
-static void emit_mov_reg_membase(struct insn *insn,
- struct buffer *buf,
- struct basic_block *bb)
-{
- if (operand_is_xmm_reg(&insn->src))
- emit_mov_xmm_membase(insn, buf, bb);
- else
- emit_mov_gpr_membase(insn, buf, bb);
-}
-
-static void __emit_memdisp(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- unsigned long disp,
- unsigned char reg_opcode)
-{
- unsigned char rex_pfx = 0, mod_rm;
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(reg_opcode))
- rex_pfx |= REX_R;
-
- mod_rm = x86_encode_mod_rm(0, reg_opcode, 5);
-
- if (rex_pfx)
- emit(buf, rex_pfx);
- emit(buf, opc);
- emit(buf, mod_rm);
- emit_imm32(buf, rip_relative(buf, disp, 4));
-}
-
-static void __emit_memdisp_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- unsigned long disp,
- enum machine_reg reg)
-{
- __emit_memdisp(buf, rex_w, opc, disp, x86_encode_reg(reg));
-}
-
-static void __emit_reg_memdisp(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg reg,
- unsigned long disp)
-{
- __emit_memdisp(buf, rex_w, opc, disp, x86_encode_reg(reg));
-}
-
-static void emit_mov_reg_memdisp(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->src);
-
- __emit_reg_memdisp(buf, rex_w, 0x89, mach_reg(&insn->src.reg), insn->dest.imm);
-}
-
-static void emit_mov_memdisp_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->dest);
-
- __emit_memdisp_reg(buf, rex_w, 0x8b, insn->src.imm, mach_reg(&insn->dest.reg));
-}
-
-static void emit_mov_thread_local_memdisp_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->dest);
-
- emit(buf, 0x64); /* FS segment override prefix */
- __emit_memdisp_reg(buf, rex_w, 0x8b, insn->src.imm, mach_reg(&insn->dest.reg));
-}
-
-static void emit_mov_reg_thread_local_memdisp(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->src);
-
- emit(buf, 0x64); /* FS segment override prefix */
- __emit_reg_memdisp(buf, rex_w, 0x89, mach_reg(&insn->src.reg), insn->dest.imm);
-}
-
-static void emit_mov_reg_thread_local_membase(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- emit(buf, 0x64); /* FS segment override prefix */
- emit_mov_reg_membase(insn, buf, bb);
-}
-
-static void __emit64_test_membase_reg(struct buffer *buf,
- enum machine_reg src,
- unsigned long disp,
- enum machine_reg dest)
-{
- __emit_membase_reg(buf, 1, 0x85, src, disp, dest);
-}
-
-#ifdef CONFIG_X86_32
-static void __emit32_test_membase_reg(struct buffer *buf,
- enum machine_reg src,
- unsigned long disp,
- enum machine_reg dest)
-{
- __emit_membase_reg(buf, 0, 0x85, src, disp, dest);
-}
-#endif
-
-static void emit_test_membase_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- emit_membase_reg(buf, is_64bit_bin_reg_op(&insn->src, &insn->dest), 0x85, &insn->src, &insn->dest);
-}
-
-static void emit_indirect_jump_reg(struct buffer *buf, enum machine_reg reg)
-{
- unsigned char reg_num = x86_encode_reg(reg);
-
- emit(buf, 0xff);
- if (reg_high(reg_num))
- emit(buf, REX_B);
- emit(buf, x86_encode_mod_rm(0x3, 0x04, reg_num));
-}
-
-static void __emit64_mov_imm_reg(struct buffer *buf,
- long imm,
- enum machine_reg reg)
-{
- __emit_reg(buf, 1, 0xb8, reg);
- emit_imm64(buf, imm);
-}
-
-static void emit_mov_imm_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->dest);
-
- __emit_reg(buf, rex_w, 0xb8, mach_reg(&insn->dest.reg));
- if (!rex_w)
- emit_imm32(buf, insn->src.imm);
- else
- emit_imm64(buf, insn->src.imm);
-}
-
-static void __emit64_mov_membase_reg(struct buffer *buf,
- enum machine_reg base_reg,
- unsigned long disp,
- enum machine_reg dest_reg)
-{
- __emit_membase_reg(buf, 1, 0x8b, base_reg, disp, dest_reg);
-}
-
-static void emit_mov_membase_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- emit_membase_reg(buf, 1, 0x8b, &insn->src, &insn->dest);
-}
-
-static void emit_mov_memlocal_gpr(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg dest_reg;
- unsigned long disp;
-
- dest_reg = mach_reg(&insn->dest.reg);
- disp = slot_offset(insn->src.slot);
-
- __emit_membase_reg(buf, 1, 0x8b, MACH_REG_RBP, disp, dest_reg);
-}
-
-static void emit_mov_memlocal_xmm(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg dest_reg;
- unsigned long disp;
- unsigned char opc[3];
-
- dest_reg = mach_reg(&insn->dest.reg);
- disp = slot_offset(insn->src.slot);
-
- if (!is_64bit_reg(&insn->dest))
- /* MOVSS */
- opc[0] = 0xF3;
- else
- /* MOVSD */
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x10;
-
- __emit_lopc_membase_reg(buf, 0, opc, 3, MACH_REG_RBP, disp, dest_reg);
-}
-
-static void emit_mov_memlocal_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- if (operand_is_xmm_reg(&insn->dest))
- emit_mov_memlocal_xmm(insn, buf, bb);
- else
- emit_mov_memlocal_gpr(insn, buf, bb);
-}
-
-static void emit_mov_reg_memlocal(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg src_reg;
- unsigned long disp;
-
- src_reg = mach_reg(&insn->src.reg);
- disp = slot_offset(insn->dest.slot);
-
- __emit_reg_membase(buf, 1, 0x89, src_reg, MACH_REG_RBP, disp);
-}
-
-static void __emit_cmp_imm_reg(struct buffer *buf, int rex_w, long imm, enum machine_reg reg)
-{
- emit_alu_imm_reg(buf, rex_w, 0x07, imm, reg);
-}
-
-static void emit_cmp_imm_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->dest);
-
- __emit_cmp_imm_reg(buf, rex_w, insn->src.imm, mach_reg(&insn->dest.reg));
-}
-
-static void emit_cmp_membase_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_reg(&insn->dest);
-
- emit_membase_reg(buf, rex_w, 0x3b, &insn->src, &insn->dest);
-}
-
-static void emit_cmp_reg_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- int rex_w = is_64bit_bin_reg_op(&insn->src, &insn->dest);
-
- emit_reg_reg(buf, rex_w, 0x39, &insn->src, &insn->dest);
-}
-
-static void __emit_test_imm_memdisp(struct buffer *buf,
- int rex_w,
- long imm,
- long disp)
-{
- /* XXX: Supports only byte or long imms */
-
- if (rex_w)
- emit(buf, REX_W);
-
- if (is_imm_8(imm))
- emit(buf, 0xf6);
- else
- emit(buf, 0xf7);
-
- emit(buf, 0x04);
- emit(buf, 0x25);
- emit_imm32(buf, disp);
- emit_imm(buf, imm);
-}
-
-static void emit_test_imm_memdisp(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_test_imm_memdisp(buf, 0, insn->src.imm, insn->dest.disp);
-}
-
-static void __emit_lopc_memindex(struct buffer *buf,
- int rex_w,
- unsigned char *lopc,
- size_t lopc_size,
- unsigned char shift,
- enum machine_reg index_reg,
- enum machine_reg base_reg,
- unsigned char reg_opcode)
-{
- int needs_disp;
- unsigned char rex_pfx = 0, mod_rm, sib;
- unsigned char __index_reg = x86_encode_reg(index_reg);
- unsigned char __base_reg = x86_encode_reg(base_reg);
-
- needs_disp = (base_reg == MACH_REG_R13);
-
- if (needs_disp)
- mod_rm = x86_encode_mod_rm(0x01, reg_opcode, 0x04);
- else
- mod_rm = x86_encode_mod_rm(0x00, reg_opcode, 0x04);
- sib = x86_encode_sib(shift, __index_reg, __base_reg);
-
- if (rex_w)
- rex_pfx |= REX_W;
- if (reg_high(reg_opcode))
- rex_pfx |= REX_R;
- if (reg_high(__index_reg))
- rex_pfx |= REX_X;
- if (reg_high(__base_reg))
- rex_pfx |= REX_B;
-
- emit_lopc(buf, rex_pfx, lopc, lopc_size);
- emit(buf, mod_rm);
- emit(buf, sib);
- if (needs_disp)
- emit(buf, 0);
-}
-
-static void __emit_memindex_reg(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- unsigned char shift,
- enum machine_reg index_reg,
- enum machine_reg base_reg,
- enum machine_reg dest_reg)
-{
- __emit_lopc_memindex(buf, rex_w, &opc, 1, shift,
- index_reg, base_reg, x86_encode_reg(dest_reg));
-}
-
-static void __emit_reg_memindex(struct buffer *buf,
- int rex_w,
- unsigned char opc,
- enum machine_reg src_reg,
- unsigned char shift,
- enum machine_reg index_reg,
- enum machine_reg base_reg)
-{
- __emit_lopc_memindex(buf, rex_w, &opc, 1, shift,
- index_reg, base_reg, x86_encode_reg(src_reg));
-}
-
-static void emit_mov_memindex_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_memindex_reg(buf, is_64bit_reg(&insn->dest), 0x8b,
- insn->src.shift, mach_reg(&insn->src.index_reg),
- mach_reg(&insn->src.base_reg), mach_reg(&insn->dest.reg));
-}
-
-static void emit_mov_reg_memindex(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_reg_memindex(buf, is_64bit_reg(&insn->src), 0x89,
- mach_reg(&insn->src.reg), insn->dest.shift,
- mach_reg(&insn->dest.index_reg),
- mach_reg(&insn->dest.base_reg));
-}
-
-static void __emit_mov_imm_membase(struct buffer *buf, long imm, enum machine_reg base, long disp)
-{
- __emit_membase(buf, 0, 0xc7, base, disp, 0);
- emit_imm32(buf, imm);
-}
-
-static void emit_mov_imm_membase(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_mov_imm_membase(buf, insn->src.imm, mach_reg(&insn->dest.base_reg), insn->dest.disp);
-}
-
-static void emit_mov_imm_memlocal(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_mov_imm_membase(buf, insn->src.imm, MACH_REG_RBP, slot_offset(insn->dest.slot));
-}
-
-static void emit_conv_fpu_to_gpr(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg src, dest;
- unsigned char opc[3];
- int rex_w;
-
- src = mach_reg(&insn->src.reg);
- dest = mach_reg(&insn->dest.reg);
-
- if (!is_64bit_reg(&insn->src))
- opc[0] = 0xF3;
- else
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x2D;
-
- rex_w = is_64bit_reg(&insn->dest);
-
- __emit_lopc_reg_reg(buf, rex_w, opc, 3, dest, src);
-}
-
-static void emit_conv_gpr_to_fpu(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg src, dest;
- unsigned char opc[3];
- int rex_w;
-
- src = mach_reg(&insn->src.reg);
- dest = mach_reg(&insn->dest.reg);
-
- if (!is_64bit_reg(&insn->dest))
- opc[0] = 0xF3;
- else
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x2A;
-
- rex_w = is_64bit_reg(&insn->src);
-
- __emit_lopc_reg_reg(buf, rex_w, opc, 3, dest, src);
-}
-
-static void emit_conv_fpu_to_fpu(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- enum machine_reg src, dest;
- unsigned char opc[3];
-
- src = mach_reg(&insn->src.reg);
- dest = mach_reg(&insn->dest.reg);
-
- if (!is_64bit_reg(&insn->src))
- opc[0] = 0xF3;
- else
- opc[0] = 0xF2;
- opc[1] = 0x0F;
- opc[2] = 0x5A;
-
- __emit_lopc_reg_reg(buf, 0, opc, 3, dest, src);
-}
-
-static void __emit_div_mul_reg_rax(struct buffer *buf,
- struct operand *src,
- struct operand *dest,
- unsigned char opc_ext)
-{
- unsigned char rex_pfx = 0, rm;
-
- assert(mach_reg(&dest->reg) == MACH_REG_RAX);
-
- rm = encode_reg(&src->reg);
-
- if (is_64bit_reg(src))
- rex_pfx |= REX_W;
- if (reg_high(rm))
- rex_pfx |= REX_B;
-
- if (rex_pfx)
- emit(buf, rex_pfx);
- emit(buf, 0xF7);
- emit(buf, x86_encode_mod_rm(0x03, opc_ext, rm));
-}
-
-static void emit_div_reg_reg(struct insn *insn, struct buffer *buf, struct basic_block *bb)
-{
- __emit_div_mul_reg_rax(buf, &insn->src, &insn->dest, 0x07);
-}
-
-static void __emit64_push_xmm(struct buffer *buf, enum machine_reg reg)
-{
- unsigned char opc[3] = { 0xF2, 0x0F, 0x11 }; /* MOVSD */
-
- __emit64_sub_imm_reg(buf, 0x08, MACH_REG_RSP);
- __emit_lopc_reg_membase(buf, 0, opc, 3, reg, MACH_REG_RSP, 0);
-}
-
-static void __emit64_pop_xmm(struct buffer *buf, enum machine_reg reg)
-{
- unsigned char opc[3] = { 0xF2, 0x0F, 0x10 }; /* MOVSD */
-
- __emit_lopc_membase_reg(buf, 0, opc, 3, MACH_REG_RSP, 0, reg);
- __emit_add_imm_reg(buf, 0x08, MACH_REG_RSP);
-}
-
-static void emit_save_callee_save_regs(struct buffer *buf)
-{
- int i;
-
- for (i = 0; i < NR_CALLEE_SAVE_REGS; i++) {
- enum machine_reg reg = callee_save_regs[i];
-
- __emit_push_reg(buf, reg);
- }
-}
-
-static void emit_restore_callee_save_regs(struct buffer *buf)
-{
- int i;
-
- for (i = 0; i < NR_CALLEE_SAVE_REGS; i++) {
- enum machine_reg reg = callee_save_regs[NR_CALLEE_SAVE_REGS - i - 1];
-
- __emit_pop_reg(buf, reg);
- }
-}
-
-void emit_prolog(struct buffer *buf, struct stack_frame *frame,
- unsigned long frame_size)
-{
- __emit_push_reg(buf, MACH_REG_RBP);
- __emit_mov_reg_reg(buf, MACH_REG_RSP, MACH_REG_RBP);
-
- /*
- * The ABI requires us to clear DF, but we
- * don't need to. Though keep this in mind:
- * emit(buf, 0xFC);
- */
-
- if (frame_size)
- __emit64_sub_imm_reg(buf, frame_size, MACH_REG_RSP);
-
- emit_save_callee_save_regs(buf);
-
- /* Save *this. */
- __emit_push_reg(buf, MACH_REG_RDI);
-}
-
-void emit_epilog(struct buffer *buf)
-{
- emit_restore_regs(buf);
- emit_leave(buf);
- emit_ret(buf);
-}
-
-static void emit_restore_regs(struct buffer *buf)
-{
- /* Clear *this from stack. */
- __emit_add_imm_reg(buf, 0x08, MACH_REG_RSP);
-
- emit_restore_callee_save_regs(buf);
-}
-
-static void emit_save_regparm(struct buffer *buf)
-{
- __emit_push_reg(buf, MACH_REG_RDI);
- __emit_push_reg(buf, MACH_REG_RSI);
- __emit_push_reg(buf, MACH_REG_RDX);
- __emit_push_reg(buf, MACH_REG_RCX);
- __emit_push_reg(buf, MACH_REG_R8);
- __emit_push_reg(buf, MACH_REG_R9);
-
- __emit64_push_xmm(buf, MACH_REG_XMM0);
- __emit64_push_xmm(buf, MACH_REG_XMM1);
- __emit64_push_xmm(buf, MACH_REG_XMM2);
- __emit64_push_xmm(buf, MACH_REG_XMM3);
- __emit64_push_xmm(buf, MACH_REG_XMM4);
- __emit64_push_xmm(buf, MACH_REG_XMM5);
- __emit64_push_xmm(buf, MACH_REG_XMM6);
- __emit64_push_xmm(buf, MACH_REG_XMM7);
-}
-
-static void emit_restore_regparm(struct buffer *buf)
-{
- __emit64_pop_xmm(buf, MACH_REG_XMM7);
- __emit64_pop_xmm(buf, MACH_REG_XMM6);
- __emit64_pop_xmm(buf, MACH_REG_XMM5);
- __emit64_pop_xmm(buf, MACH_REG_XMM4);
- __emit64_pop_xmm(buf, MACH_REG_XMM3);
- __emit64_pop_xmm(buf, MACH_REG_XMM2);
- __emit64_pop_xmm(buf, MACH_REG_XMM1);
- __emit64_pop_xmm(buf, MACH_REG_XMM0);
-
- __emit_pop_reg(buf, MACH_REG_R9);
- __emit_pop_reg(buf, MACH_REG_R8);
- __emit_pop_reg(buf, MACH_REG_RCX);
- __emit_pop_reg(buf, MACH_REG_RDX);
- __emit_pop_reg(buf, MACH_REG_RSI);
- __emit_pop_reg(buf, MACH_REG_RDI);
-}
-
-void emit_trampoline(struct compilation_unit *cu,
- void *call_target,
- struct jit_trampoline *trampoline)
-{
- struct buffer *buf = trampoline->objcode;
-
- jit_text_lock();
-
- buf->buf = jit_text_ptr();
-
- /* This is for __builtin_return_address() to work and to access
- call arguments in correct manner. */
- __emit_push_reg(buf, MACH_REG_RBP);
- __emit_mov_reg_reg(buf, MACH_REG_RSP, MACH_REG_RBP);
-
- /*
- * %rdi, %rsi, %rdx, %rcx, %r8 and %r9 are used
- * to pass parameters, so save them if they get modified.
- */
- emit_save_regparm(buf);
-
- __emit64_mov_imm_reg(buf, (unsigned long) cu, MACH_REG_RDI);
- __emit_call(buf, call_target);
-
- /*
- * Test for exception occurrence.
- * We do this by polling a dedicated thread-specific pointer,
- * which triggers SIGSEGV when exception is set.
- *
- * mov fs:(0xXXX), %rcx
- * test (%rcx), %rcx
- */
- emit(buf, 0x64);
- __emit_memdisp_reg(buf, 1, 0x8b,
- get_thread_local_offset(&trampoline_exception_guard),
- MACH_REG_RCX);
- __emit64_test_membase_reg(buf, MACH_REG_RCX, 0, MACH_REG_RCX);
-
- if (method_is_virtual(cu->method)) {
- unsigned long this_disp;
-
- if (vm_method_is_jni(cu->method))
- this_disp = -0x10;
- else
- this_disp = -0x08;
-
- __emit_push_reg(buf, MACH_REG_RAX);
- __emit64_mov_imm_reg(buf, (unsigned long) cu, MACH_REG_RDI);
- __emit64_mov_membase_reg(buf, MACH_REG_RBP, this_disp, MACH_REG_RSI);
- __emit_mov_reg_reg(buf, MACH_REG_RAX, MACH_REG_RDX);
- __emit_call(buf, fixup_vtable);
-
- __emit_pop_reg(buf, MACH_REG_RAX);
- }
-
- emit_restore_regparm(buf);
-
- __emit_pop_reg(buf, MACH_REG_RBP);
- emit_indirect_jump_reg(buf, MACH_REG_RAX);
-
- jit_text_reserve(buffer_offset(buf));
- jit_text_unlock();
-}
-
-static void emit_exception_test(struct buffer *buf, enum machine_reg reg)
-{
- /* mov fs:(0xXXX), %reg */
- emit(buf, 0x64);
- __emit_memdisp_reg(buf, 1, 0x8b,
- get_thread_local_offset(&exception_guard), reg);
-
- /* test (%reg), %reg */
- __emit64_test_membase_reg(buf, reg, 0, reg);
-}
-
-void emit_lock(struct buffer *buf, struct vm_object *obj)
-{
- emit_save_regparm(buf);
-
- __emit64_mov_imm_reg(buf, (unsigned long) obj, MACH_REG_RDI);
- __emit_call(buf, vm_object_lock);
-
- emit_restore_regparm(buf);
-
- __emit_push_reg(buf, MACH_REG_RAX);
- emit_exception_test(buf, MACH_REG_RAX);
- __emit_pop_reg(buf, MACH_REG_RAX);
-}
-
-void emit_unlock(struct buffer *buf, struct vm_object *obj)
-{
- __emit_push_reg(buf, MACH_REG_RAX);
- emit_save_regparm(buf);
-
- __emit64_mov_imm_reg(buf, (unsigned long) obj, MACH_REG_RDI);
- __emit_call(buf, vm_object_unlock);
-
- emit_exception_test(buf, MACH_REG_RAX);
-
- emit_restore_regparm(buf);
- __emit_pop_reg(buf, MACH_REG_RAX);
-}
-
-void emit_lock_this(struct buffer *buf)
-{
- __emit64_mov_membase_reg(buf, MACH_REG_RSP, 0x00, MACH_REG_RDI);
- emit_save_regparm(buf);
- __emit_call(buf, vm_object_lock);
- emit_restore_regparm(buf);
-
- __emit_push_reg(buf, MACH_REG_RAX);
- emit_exception_test(buf, MACH_REG_RAX);
- __emit_pop_reg(buf, MACH_REG_RAX);
-}
-
-void emit_unlock_this(struct buffer *buf)
-{
- __emit64_mov_membase_reg(buf, MACH_REG_RSP, 0x00, MACH_REG_RDI);
- __emit_push_reg(buf, MACH_REG_RAX);
- emit_save_regparm(buf);
- __emit_call(buf, vm_object_unlock);
-
- emit_exception_test(buf, MACH_REG_RAX);
-
- emit_restore_regparm(buf);
- __emit_pop_reg(buf, MACH_REG_RAX);
-}
-
-
-void *emit_ic_check(struct buffer *buf)
-{
- return NULL;
-}
-
-void emit_ic_miss_handler(struct buffer *buf, void *ic_check, struct vm_method *vmm)
-{
-}
-#endif /* CONFIG_X86_32 */
-
extern void jni_trampoline(void);
void emit_jni_trampoline(struct buffer *buf, struct vm_method *vmm,
@@ -2221,13 +1043,7 @@ void emit_jni_trampoline(struct buffer *buf, struct vm_method *vmm,
__emit_pop_reg(buf, MACH_REG_xAX); /* return address */
__emit_push_reg(buf, MACH_REG_xAX);
-#ifdef CONFIG_X86_32
__emit_push_imm(buf, (unsigned long) target);
-#else
- __emit64_sub_imm_reg(buf, sizeof(unsigned long), MACH_REG_RSP);
- __emit_mov_imm_membase(buf, (((unsigned long) target) >> 32) & 0xFFFFFFFFUL, MACH_REG_RSP, 0x04);
- __emit_mov_imm_membase(buf, (((unsigned long) target) >> 0) & 0xFFFFFFFFUL, MACH_REG_RSP, 0x00);
-#endif
__emit_push_reg(buf, MACH_REG_xAX);
__emit_push_imm(buf, (unsigned long) vmm);
__emit_push_reg(buf, MACH_REG_xBP);
@@ -2443,7 +1259,6 @@ static struct emitter emitters[] = {
DECL_EMITTER(INSN_XORPS_XMM_XMM, insn_encode),
DECL_EMITTER(INSN_XOR_MEMBASE_REG, insn_encode),
DECL_EMITTER(INSN_XOR_REG_REG, insn_encode),
-#ifdef CONFIG_X86_32
DECL_EMITTER(INSN_ADC_IMM_REG, insn_encode),
DECL_EMITTER(INSN_ADC_MEMBASE_REG, insn_encode),
DECL_EMITTER(INSN_ADC_REG_REG, insn_encode),
@@ -2496,31 +1311,6 @@ static struct emitter emitters[] = {
DECL_EMITTER(INSN_SUB_MEMBASE_REG, insn_encode),
DECL_EMITTER(INSN_TEST_IMM_MEMDISP, emit_test_imm_memdisp),
DECL_EMITTER(INSN_TEST_MEMBASE_REG, insn_encode),
-#else /* CONFIG_X86_64 */
- DECL_EMITTER(INSN_CMP_IMM_REG, emit_cmp_imm_reg),
- DECL_EMITTER(INSN_CMP_MEMBASE_REG, emit_cmp_membase_reg),
- DECL_EMITTER(INSN_CMP_REG_REG, emit_cmp_reg_reg),
- DECL_EMITTER(INSN_CONV_FPU_TO_GPR, emit_conv_fpu_to_gpr),
- DECL_EMITTER(INSN_CONV_GPR_TO_FPU, emit_conv_gpr_to_fpu),
- DECL_EMITTER(INSN_CONV_XMM_TO_XMM64, emit_conv_fpu_to_fpu),
- DECL_EMITTER(INSN_CONV_XMM64_TO_XMM, emit_conv_fpu_to_fpu),
- DECL_EMITTER(INSN_DIV_REG_REG, emit_div_reg_reg),
- DECL_EMITTER(INSN_MOV_MEMBASE_REG, emit_mov_membase_reg),
- DECL_EMITTER(INSN_MOV_MEMDISP_REG, emit_mov_memdisp_reg),
- DECL_EMITTER(INSN_MOV_MEMINDEX_REG, emit_mov_memindex_reg),
- DECL_EMITTER(INSN_MOV_MEMLOCAL_REG, emit_mov_memlocal_reg),
- DECL_EMITTER(INSN_MOV_REG_MEMBASE, emit_mov_reg_membase),
- DECL_EMITTER(INSN_MOV_REG_MEMDISP, emit_mov_reg_memdisp),
- DECL_EMITTER(INSN_MOV_REG_MEMINDEX, emit_mov_reg_memindex),
- DECL_EMITTER(INSN_MOV_REG_MEMLOCAL, emit_mov_reg_memlocal),
- DECL_EMITTER(INSN_MOV_REG_THREAD_LOCAL_MEMBASE, emit_mov_reg_thread_local_membase),
- DECL_EMITTER(INSN_MOV_REG_THREAD_LOCAL_MEMDISP, emit_mov_reg_thread_local_memdisp),
- DECL_EMITTER(INSN_MOV_THREAD_LOCAL_MEMDISP_REG, emit_mov_thread_local_memdisp_reg),
- DECL_EMITTER(INSN_MUL_REG_REG, emit_mul_reg_reg),
- DECL_EMITTER(INSN_PUSH_IMM, emit_push_imm),
- DECL_EMITTER(INSN_TEST_MEMBASE_REG, emit_test_membase_reg),
- DECL_EMITTER(INSN_TEST_IMM_MEMDISP, emit_test_imm_memdisp),
-#endif
};
static void __emit_insn(struct buffer *buf, struct basic_block *bb, struct insn *insn)