We can reuse much x86-32 code on x86-64 due to their similarity. This splits such reusable code into a separate file that is meant to be included from emit-code_32.c and emit-code_64.c.
Signed-off-by: Eduard - Gabriel Munteanu <eduard.munte...@linux360.ro> --- arch/x86/emit-code.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/emit-code_32.c | 349 ++-------------------------------------------- 2 files changed, 366 insertions(+), 338 deletions(-) create mode 100644 arch/x86/emit-code.c diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c new file mode 100644 index 0000000..bc387ee --- /dev/null +++ b/arch/x86/emit-code.c @@ -0,0 +1,355 @@ +/* + * x86 generic code emitter. + * + * Copyright (C) 2006 Pekka Enberg + * + * This file is released under the GPL version 2. Please refer to the file + * LICENSE for details. + */ + +#include <arch/registers.h> + +#include <stdio.h> + +enum emitter_type { + NO_OPERANDS = 1, + SINGLE_OPERAND, + TWO_OPERANDS, + BRANCH, +}; + +struct emitter { + void *emit_fn; + enum emitter_type type; +}; + +/* These must be defined in the file that included us. */ +static unsigned char __encode_reg(enum machine_reg reg); +static void backpatch_branch_target(struct buffer *buf, + struct insn *insn, + unsigned long target_offset); +static void emit_imm(struct buffer *buf, long imm); +void emit_branch_rel(struct buffer *buf, unsigned char prefix, + unsigned char opc, long rel32); +static struct emitter emitters[]; + +static unsigned char encode_reg(struct use_position *reg) +{ + return __encode_reg(mach_reg(reg)); +} + +/** + * encode_modrm: Encode a ModR/M byte of an IA-32 instruction. + * @mod: The mod field of the byte. + * @reg_opcode: The reg/opcode field of the byte. + * @rm: The r/m field of the byte. + */ +static inline unsigned char encode_modrm(unsigned char mod, + unsigned char reg_opcode, + unsigned char rm) +{ + return ((mod & 0x3) << 6) | ((reg_opcode & 0x7) << 3) | (rm & 0x7); +} + +static inline bool is_imm_8(long imm) +{ + return (imm >= -128) && (imm <= 127); +} + +static inline void emit(struct buffer *buf, unsigned char c) +{ + int err; + + err = append_buffer(buf, c); + assert(!err); +} + +static void emit_imm32(struct buffer *buf, int imm) +{ + union { + int val; + unsigned char b[4]; + } 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]); +} + +static void __emit_push_reg(struct buffer *buf, enum machine_reg reg) +{ + emit(buf, 0x50 + __encode_reg(reg)); +} + +static void emit_push_reg(struct buffer *buf, struct operand *operand) +{ + __emit_push_reg(buf, mach_reg(&operand->reg)); +} + +static void __emit_pop_reg(struct buffer *buf, enum machine_reg reg) +{ + emit(buf, 0x58 + __encode_reg(reg)); +} + +static void emit_pop_reg(struct buffer *buf, struct operand *operand) +{ + __emit_pop_reg(buf, mach_reg(&operand->reg)); +} + +void emit_ret(struct buffer *buf) +{ + emit(buf, 0xc3); +} + +static void +__emit_reg_reg(struct buffer *buf, unsigned char opc, + enum machine_reg direct_reg, enum machine_reg rm_reg) +{ + unsigned char mod_rm; + + mod_rm = encode_modrm(0x03, __encode_reg(direct_reg), __encode_reg(rm_reg)); + + emit(buf, opc); + emit(buf, mod_rm); +} + +static void +emit_reg_reg(struct buffer *buf, 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, opc, direct_reg, rm_reg); +} + +static void __emit_mov_reg_reg(struct buffer *buf, enum machine_reg src_reg, + enum machine_reg dest_reg) +{ + __emit_reg_reg(buf, 0x89, src_reg, dest_reg); +} + +static void emit_mov_reg_reg(struct buffer *buf, struct operand *src, + struct operand *dest) +{ + __emit_mov_reg_reg(buf, mach_reg(&src->reg), mach_reg(&dest->reg)); +} + +static void emit_alu_imm_reg(struct buffer *buf, unsigned char opc_ext, + long imm, enum machine_reg reg) +{ + int opc; + + if (is_imm_8(imm)) + opc = 0x83; + else + opc = 0x81; + + emit(buf, opc); + emit(buf, encode_modrm(0x3, opc_ext, __encode_reg(reg))); + emit_imm(buf, imm); +} + +static void __emit_sub_imm_reg(struct buffer *buf, unsigned long imm, + enum machine_reg reg) +{ + emit_alu_imm_reg(buf, 0x05, imm, reg); +} + +static void emit_sub_imm_reg(struct buffer *buf, struct operand *src, + struct operand *dest) +{ + __emit_sub_imm_reg(buf, src->imm, mach_reg(&dest->reg)); +} + +static void emit_indirect_jump_reg(struct buffer *buf, enum machine_reg reg) +{ + emit(buf, 0xff); + emit(buf, encode_modrm(0x3, 0x04, __encode_reg(reg))); +} + +#define PREFIX_SIZE 1 +#define BRANCH_INSN_SIZE 5 +#define BRANCH_TARGET_OFFSET 1 + +static long branch_rel_addr(struct insn *insn, unsigned long target_offset) +{ + long ret; + + ret = target_offset - insn->mach_offset - BRANCH_INSN_SIZE; + if (insn->escaped) + ret -= PREFIX_SIZE; + + return ret; +} + +static void __emit_branch(struct buffer *buf, unsigned char prefix, + unsigned char opc, struct insn *insn) +{ + struct basic_block *target_bb; + long addr = 0; + + if (prefix) + insn->escaped = true; + + target_bb = insn->operand.branch_target; + + if (target_bb->is_emitted) { + struct insn *target_insn = + list_first_entry(&target_bb->insn_list, struct insn, + insn_list_node); + + addr = branch_rel_addr(insn, target_insn->mach_offset); + } else + list_add(&insn->branch_list_node, &target_bb->backpatch_insns); + + emit_branch_rel(buf, prefix, opc, addr); +} + +static void emit_je_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x84, insn); +} + +static void emit_jne_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x85, insn); +} + +static void emit_jge_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x8d, insn); +} + +static void emit_jg_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x8f, insn); +} + +static void emit_jle_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x8e, insn); +} + +static void emit_jl_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x0f, 0x8c, insn); +} + +static void emit_jmp_branch(struct buffer *buf, struct insn *insn) +{ + __emit_branch(buf, 0x00, 0xe9, insn); +} + +static void emit_indirect_call(struct buffer *buf, struct operand *operand) +{ + emit(buf, 0xff); + emit(buf, encode_modrm(0x0, 0x2, encode_reg(&operand->reg))); +} + +#define DECL_EMITTER(_insn_type, _fn, _emitter_type) \ + [_insn_type] = { .emit_fn = _fn, .type = _emitter_type } + +#define GENERIC_X86_EMITTERS \ + DECL_EMITTER(INSN_JE_BRANCH, emit_je_branch, BRANCH), \ + DECL_EMITTER(INSN_JGE_BRANCH, emit_jge_branch, BRANCH), \ + DECL_EMITTER(INSN_JG_BRANCH, emit_jg_branch, BRANCH), \ + DECL_EMITTER(INSN_JLE_BRANCH, emit_jle_branch, BRANCH), \ + DECL_EMITTER(INSN_JL_BRANCH, emit_jl_branch, BRANCH), \ + DECL_EMITTER(INSN_JMP_BRANCH, emit_jmp_branch, BRANCH), \ + DECL_EMITTER(INSN_JNE_BRANCH, emit_jne_branch, BRANCH), \ + DECL_EMITTER(INSN_MOV_REG_REG, emit_mov_reg_reg, TWO_OPERANDS), \ + DECL_EMITTER(INSN_PUSH_REG, emit_push_reg, SINGLE_OPERAND), \ + DECL_EMITTER(INSN_POP_REG, emit_pop_reg, SINGLE_OPERAND), \ + DECL_EMITTER(INSN_SUB_IMM_REG, emit_sub_imm_reg, TWO_OPERANDS) + +typedef void (*emit_no_operands_fn) (struct buffer *); + +static void emit_no_operands(struct emitter *emitter, struct buffer *buf) +{ + emit_no_operands_fn emit = emitter->emit_fn; + emit(buf); +} + +typedef void (*emit_single_operand_fn) (struct buffer *, struct operand * operand); + +static void emit_single_operand(struct emitter *emitter, struct buffer *buf, struct insn *insn) +{ + emit_single_operand_fn emit = emitter->emit_fn; + emit(buf, &insn->operand); +} + +typedef void (*emit_two_operands_fn) (struct buffer *, struct operand * src, struct operand * dest); + +static void emit_two_operands(struct emitter *emitter, struct buffer *buf, struct insn *insn) +{ + emit_two_operands_fn emit = emitter->emit_fn; + emit(buf, &insn->src, &insn->dest); +} + +typedef void (*emit_branch_fn) (struct buffer *, struct insn *); + +static void emit_branch(struct emitter *emitter, struct buffer *buf, struct insn *insn) +{ + emit_branch_fn emit = emitter->emit_fn; + emit(buf, insn); +} + +static void __emit_insn(struct buffer *buf, struct insn *insn) +{ + struct emitter *emitter; + + emitter = &emitters[insn->type]; + switch (emitter->type) { + case NO_OPERANDS: + emit_no_operands(emitter, buf); + break; + case SINGLE_OPERAND: + emit_single_operand(emitter, buf, insn); + break; + case TWO_OPERANDS: + emit_two_operands(emitter, buf, insn); + break; + case BRANCH: + emit_branch(emitter, buf, insn); + break; + default: + printf("Oops. No emitter for 0x%x.\n", insn->type); + abort(); + }; +} + +static void emit_insn(struct buffer *buf, struct insn *insn) +{ + insn->mach_offset = buffer_offset(buf); + __emit_insn(buf, insn); +} + +static void backpatch_branches(struct buffer *buf, + struct list_head *to_backpatch, + unsigned long target_offset) +{ + struct insn *this, *next; + + list_for_each_entry_safe(this, next, to_backpatch, branch_list_node) { + backpatch_branch_target(buf, this, target_offset); + list_del(&this->branch_list_node); + } +} + +void emit_body(struct basic_block *bb, struct buffer *buf) +{ + struct insn *insn; + + backpatch_branches(buf, &bb->backpatch_insns, buffer_offset(buf)); + + for_each_insn(insn, &bb->insn_list) { + emit_insn(buf, insn); + } + bb->is_emitted = true; +} + diff --git a/arch/x86/emit-code_32.c b/arch/x86/emit-code_32.c index 5160cce..c799c4b 100644 --- a/arch/x86/emit-code_32.c +++ b/arch/x86/emit-code_32.c @@ -27,6 +27,8 @@ #include <stdbool.h> #include <string.h> +#include "emit-code.c" + /* * __encode_reg: Encode register to be used in IA-32 instruction. * @reg: Register to encode. @@ -69,43 +71,12 @@ static unsigned char __encode_reg(enum machine_reg reg) return ret; } -static unsigned char encode_reg(struct use_position *reg) -{ - return __encode_reg(mach_reg(reg)); -} - -static inline bool is_imm_8(long imm) -{ - return (imm >= -128) && (imm <= 127); -} - -/** - * encode_modrm: Encode a ModR/M byte of an IA-32 instruction. - * @mod: The mod field of the byte. - * @reg_opcode: The reg/opcode field of the byte. - * @rm: The r/m field of the byte. - */ -static inline unsigned char encode_modrm(unsigned char mod, - unsigned char reg_opcode, - unsigned char rm) -{ - return ((mod & 0x3) << 6) | ((reg_opcode & 0x7) << 3) | (rm & 0x7); -} - static inline unsigned char encode_sib(unsigned char scale, unsigned char index, unsigned char base) { return ((scale & 0x3) << 6) | ((index & 0x7) << 3) | (base & 0x7); } -static inline void emit(struct buffer *buf, unsigned char c) -{ - int err; - - err = append_buffer(buf, c); - assert(!err); -} - static void write_imm32(struct buffer *buf, unsigned long offset, long imm32) { unsigned char *buffer; @@ -123,20 +94,6 @@ static void write_imm32(struct buffer *buf, unsigned long offset, long imm32) buffer[offset + 3] = imm_buf.b[3]; } -static void emit_imm32(struct buffer *buf, int imm) -{ - union { - int val; - unsigned char b[4]; - } 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]); -} - static void emit_imm(struct buffer *buf, long imm) { if (is_imm_8(imm)) @@ -145,30 +102,6 @@ static void emit_imm(struct buffer *buf, long imm) emit_imm32(buf, imm); } -static void -__emit_reg_reg(struct buffer *buf, unsigned char opc, - enum machine_reg direct_reg, enum machine_reg rm_reg) -{ - unsigned char mod_rm; - - mod_rm = encode_modrm(0x03, __encode_reg(direct_reg), __encode_reg(rm_reg)); - - emit(buf, opc); - emit(buf, mod_rm); -} - -static void -emit_reg_reg(struct buffer *buf, 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, opc, direct_reg, rm_reg); -} - static void __emit_membase_reg(struct buffer *buf, unsigned char opc, enum machine_reg base_reg, unsigned long disp, @@ -215,39 +148,12 @@ emit_membase_reg(struct buffer *buf, unsigned char opc, struct operand *src, __emit_membase_reg(buf, opc, base_reg, disp, dest_reg); } -static void __emit_push_reg(struct buffer *buf, enum machine_reg reg) -{ - emit(buf, 0x50 + __encode_reg(reg)); -} - static void __emit_push_membase(struct buffer *buf, enum machine_reg src_reg, unsigned long disp) { __emit_membase_reg(buf, 0xff, src_reg, disp, REG_ESI); } -static void __emit_pop_reg(struct buffer *buf, enum machine_reg reg) -{ - emit(buf, 0x58 + __encode_reg(reg)); -} - -static void emit_push_reg(struct buffer *buf, struct operand *operand) -{ - __emit_push_reg(buf, mach_reg(&operand->reg)); -} - -static void __emit_mov_reg_reg(struct buffer *buf, enum machine_reg src_reg, - enum machine_reg dest_reg) -{ - __emit_reg_reg(buf, 0x89, src_reg, dest_reg); -} - -static void emit_mov_reg_reg(struct buffer *buf, struct operand *src, - struct operand *dest) -{ - __emit_mov_reg_reg(buf, mach_reg(&src->reg), mach_reg(&dest->reg)); -} - static void emit_mov_memlocal_reg(struct buffer *buf, struct operand *src, struct operand *dest) { @@ -343,33 +249,6 @@ static void emit_mov_reg_memindex(struct buffer *buf, struct operand *src, emit(buf, encode_sib(dest->shift, encode_reg(&dest->index_reg), encode_reg(&dest->base_reg))); } -static void emit_alu_imm_reg(struct buffer *buf, unsigned char opc_ext, - long imm, enum machine_reg reg) -{ - int opc; - - if (is_imm_8(imm)) - opc = 0x83; - else - opc = 0x81; - - emit(buf, opc); - emit(buf, encode_modrm(0x3, opc_ext, __encode_reg(reg))); - emit_imm(buf, imm); -} - -static void __emit_sub_imm_reg(struct buffer *buf, unsigned long imm, - enum machine_reg reg) -{ - emit_alu_imm_reg(buf, 0x05, imm, reg); -} - -static void emit_sub_imm_reg(struct buffer *buf, struct operand *src, - struct operand *dest) -{ - __emit_sub_imm_reg(buf, src->imm, mach_reg(&dest->reg)); -} - static void emit_sub_reg_reg(struct buffer *buf, struct operand *src, struct operand *dest) { @@ -408,11 +287,6 @@ void emit_prolog(struct buffer *buf, unsigned long nr_locals) __emit_sub_imm_reg(buf, nr_locals * sizeof(unsigned long), REG_ESP); } -static void emit_pop_reg(struct buffer *buf, struct operand *operand) -{ - __emit_pop_reg(buf, mach_reg(&operand->reg)); -} - static void __emit_push_imm(struct buffer *buf, long imm) { unsigned char opc; @@ -446,11 +320,6 @@ static void emit_call(struct buffer *buf, struct operand *operand) __emit_call(buf, (void *)operand->rel); } -void emit_ret(struct buffer *buf) -{ - emit(buf, 0xc3); -} - void emit_epilog(struct buffer *buf, unsigned long nr_locals) { if (nr_locals) @@ -666,100 +535,6 @@ static void emit_cmp_reg_reg(struct buffer *buf, struct operand *src, struct ope emit_reg_reg(buf, 0x39, src, dest); } -static void emit_indirect_jump_reg(struct buffer *buf, enum machine_reg reg) -{ - emit(buf, 0xff); - emit(buf, encode_modrm(0x3, 0x04, __encode_reg(reg))); -} - -void emit_branch_rel(struct buffer *buf, unsigned char prefix, - unsigned char opc, long rel32) -{ - if (prefix) - emit(buf, prefix); - emit(buf, opc); - emit_imm32(buf, rel32); -} - -#define PREFIX_SIZE 1 -#define BRANCH_INSN_SIZE 5 -#define BRANCH_TARGET_OFFSET 1 - -static long branch_rel_addr(struct insn *insn, unsigned long target_offset) -{ - long ret; - - ret = target_offset - insn->mach_offset - BRANCH_INSN_SIZE; - if (insn->escaped) - ret -= PREFIX_SIZE; - - return ret; -} - -static void __emit_branch(struct buffer *buf, unsigned char prefix, - unsigned char opc, struct insn *insn) -{ - struct basic_block *target_bb; - long addr = 0; - - if (prefix) - insn->escaped = true; - - target_bb = insn->operand.branch_target; - - if (target_bb->is_emitted) { - struct insn *target_insn = - list_first_entry(&target_bb->insn_list, struct insn, - insn_list_node); - - addr = branch_rel_addr(insn, target_insn->mach_offset); - } else - list_add(&insn->branch_list_node, &target_bb->backpatch_insns); - - emit_branch_rel(buf, prefix, opc, addr); -} - -static void emit_je_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x84, insn); -} - -static void emit_jne_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x85, insn); -} - -static void emit_jge_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x8d, insn); -} - -static void emit_jg_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x8f, insn); -} - -static void emit_jle_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x8e, insn); -} - -static void emit_jl_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x0f, 0x8c, insn); -} - -static void emit_jmp_branch(struct buffer *buf, struct insn *insn) -{ - __emit_branch(buf, 0x00, 0xe9, insn); -} - -static void emit_indirect_call(struct buffer *buf, struct operand *operand) -{ - emit(buf, 0xff); - emit(buf, encode_modrm(0x0, 0x2, encode_reg(&operand->reg))); -} - static void emit_xor_membase_reg(struct buffer *buf, struct operand *src, struct operand *dest) { @@ -777,22 +552,17 @@ static void emit_xor_imm_reg(struct buffer *buf, struct operand * src, __emit_xor_imm_reg(buf, src->imm, mach_reg(&dest->reg)); } -enum emitter_type { - NO_OPERANDS = 1, - SINGLE_OPERAND, - TWO_OPERANDS, - BRANCH, -}; - -struct emitter { - void *emit_fn; - enum emitter_type type; -}; - -#define DECL_EMITTER(_insn_type, _fn, _emitter_type) \ - [_insn_type] = { .emit_fn = _fn, .type = _emitter_type } +void emit_branch_rel(struct buffer *buf, unsigned char prefix, + unsigned char opc, long rel32) +{ + if (prefix) + emit(buf, prefix); + emit(buf, opc); + emit_imm32(buf, rel32); +} static struct emitter emitters[] = { + GENERIC_X86_EMITTERS, DECL_EMITTER(INSN_ADC_IMM_REG, emit_adc_imm_reg, TWO_OPERANDS), DECL_EMITTER(INSN_ADC_REG_REG, emit_adc_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_ADC_MEMBASE_REG, emit_adc_membase_reg, TWO_OPERANDS), @@ -807,13 +577,6 @@ static 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_DIV_MEMBASE_REG, emit_div_membase_reg, TWO_OPERANDS), - DECL_EMITTER(INSN_JE_BRANCH, emit_je_branch, BRANCH), - DECL_EMITTER(INSN_JGE_BRANCH, emit_jge_branch, BRANCH), - DECL_EMITTER(INSN_JG_BRANCH, emit_jg_branch, BRANCH), - DECL_EMITTER(INSN_JLE_BRANCH, emit_jle_branch, BRANCH), - DECL_EMITTER(INSN_JL_BRANCH, emit_jl_branch, BRANCH), - DECL_EMITTER(INSN_JMP_BRANCH, emit_jmp_branch, BRANCH), - DECL_EMITTER(INSN_JNE_BRANCH, emit_jne_branch, BRANCH), 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_MEMLOCAL_REG, emit_mov_memlocal_reg, TWO_OPERANDS), @@ -822,7 +585,6 @@ static struct emitter emitters[] = { DECL_EMITTER(INSN_MOV_REG_MEMBASE, emit_mov_reg_membase, TWO_OPERANDS), DECL_EMITTER(INSN_MOV_REG_MEMINDEX, emit_mov_reg_memindex, TWO_OPERANDS), DECL_EMITTER(INSN_MOV_REG_MEMLOCAL, emit_mov_reg_memlocal, TWO_OPERANDS), - DECL_EMITTER(INSN_MOV_REG_REG, emit_mov_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_MUL_MEMBASE_EAX, emit_mul_membase_eax, TWO_OPERANDS), DECL_EMITTER(INSN_MUL_REG_EAX, emit_mul_reg_eax, TWO_OPERANDS), DECL_EMITTER(INSN_MUL_REG_REG, emit_mul_reg_reg, TWO_OPERANDS), @@ -830,8 +592,6 @@ static struct emitter emitters[] = { DECL_EMITTER(INSN_OR_MEMBASE_REG, emit_or_membase_reg, TWO_OPERANDS), DECL_EMITTER(INSN_OR_REG_REG, emit_or_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_PUSH_IMM, emit_push_imm, SINGLE_OPERAND), - DECL_EMITTER(INSN_PUSH_REG, emit_push_reg, SINGLE_OPERAND), - DECL_EMITTER(INSN_POP_REG, emit_pop_reg, SINGLE_OPERAND), DECL_EMITTER(INSN_SAR_IMM_REG, emit_sar_imm_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SAR_REG_REG, emit_sar_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SBB_IMM_REG, emit_sbb_imm_reg, TWO_OPERANDS), @@ -839,75 +599,12 @@ static struct emitter emitters[] = { DECL_EMITTER(INSN_SBB_REG_REG, emit_sbb_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SHL_REG_REG, emit_shl_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SHR_REG_REG, emit_shr_reg_reg, TWO_OPERANDS), - DECL_EMITTER(INSN_SUB_IMM_REG, emit_sub_imm_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SUB_MEMBASE_REG, emit_sub_membase_reg, TWO_OPERANDS), DECL_EMITTER(INSN_SUB_REG_REG, emit_sub_reg_reg, TWO_OPERANDS), DECL_EMITTER(INSN_XOR_MEMBASE_REG, emit_xor_membase_reg, TWO_OPERANDS), DECL_EMITTER(INSN_XOR_IMM_REG, emit_xor_imm_reg, TWO_OPERANDS), }; -typedef void (*emit_no_operands_fn) (struct buffer *); - -static void emit_no_operands(struct emitter *emitter, struct buffer *buf) -{ - emit_no_operands_fn emit = emitter->emit_fn; - emit(buf); -} - -typedef void (*emit_single_operand_fn) (struct buffer *, struct operand * operand); - -static void emit_single_operand(struct emitter *emitter, struct buffer *buf, struct insn *insn) -{ - emit_single_operand_fn emit = emitter->emit_fn; - emit(buf, &insn->operand); -} - -typedef void (*emit_two_operands_fn) (struct buffer *, struct operand * src, struct operand * dest); - -static void emit_two_operands(struct emitter *emitter, struct buffer *buf, struct insn *insn) -{ - emit_two_operands_fn emit = emitter->emit_fn; - emit(buf, &insn->src, &insn->dest); -} - -typedef void (*emit_branch_fn) (struct buffer *, struct insn *); - -static void emit_branch(struct emitter *emitter, struct buffer *buf, struct insn *insn) -{ - emit_branch_fn emit = emitter->emit_fn; - emit(buf, insn); -} - -static void __emit_insn(struct buffer *buf, struct insn *insn) -{ - struct emitter *emitter; - - emitter = &emitters[insn->type]; - switch (emitter->type) { - case NO_OPERANDS: - emit_no_operands(emitter, buf); - break; - case SINGLE_OPERAND: - emit_single_operand(emitter, buf, insn); - break; - case TWO_OPERANDS: - emit_two_operands(emitter, buf, insn); - break; - case BRANCH: - emit_branch(emitter, buf, insn); - break; - default: - printf("Oops. No emitter for 0x%x.\n", insn->type); - abort(); - }; -} - -static void emit_insn(struct buffer *buf, struct insn *insn) -{ - insn->mach_offset = buffer_offset(buf); - __emit_insn(buf, insn); -} - static void backpatch_branch_target(struct buffer *buf, struct insn *insn, unsigned long target_offset) @@ -924,30 +621,6 @@ static void backpatch_branch_target(struct buffer *buf, write_imm32(buf, backpatch_offset, relative_addr); } -static void backpatch_branches(struct buffer *buf, - struct list_head *to_backpatch, - unsigned long target_offset) -{ - struct insn *this, *next; - - list_for_each_entry_safe(this, next, to_backpatch, branch_list_node) { - backpatch_branch_target(buf, this, target_offset); - list_del(&this->branch_list_node); - } -} - -void emit_body(struct basic_block *bb, struct buffer *buf) -{ - struct insn *insn; - - backpatch_branches(buf, &bb->backpatch_insns, buffer_offset(buf)); - - for_each_insn(insn, &bb->insn_list) { - emit_insn(buf, insn); - } - bb->is_emitted = true; -} - /* * This fixes relative calls generated by EXPR_INVOKE. * -- 1.6.0.6 ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel