diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-01-14 12:54:39 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-01-14 12:57:15 +0200 |
commit | 00ec60f2828bfcb765f96c5075d9ceb9ca8a0023 (patch) | |
tree | 88e38d7a53778cdf54b50c632a07e493e2bcb80a | |
parent | 0ab0e6fa38af8acb500e7c0e75b386a68ad4771a (diff) | |
download | jato-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.c | 1210 |
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) |