X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=c138bd4fcfe8dcca9724e914b7de25fbc0ba9d87;hb=8405f4184e2a8957906d2af04c0d0a3dfe15bb88;hp=650e0c1b98dac47943d6ee5a69393404da0fecba;hpb=2b2ac3630c2687e20d33502fbdf7a3bc073be5f4;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 650e0c1b9..c138bd4fc 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -12,6 +12,7 @@ #include "irprintf.h" #include "irop_t.h" #include "irargs_t.h" +#include "irprog_t.h" #include "../besched.h" @@ -29,10 +30,15 @@ # define obstack_chunk_free free #endif +extern int obstack_printf(struct obstack *obst, char *fmt, ...); + #define SNPRINTF_BUF_LEN 128 static const arch_env_t *arch_env = NULL; +/** + * Emits registers and/or address mode of a binary operation. + */ char *ia32_emit_binop(const ir_node *n) { static char *buf = NULL; @@ -65,6 +71,9 @@ char *ia32_emit_binop(const ir_node *n) { return buf; } +/** + * Emits registers and/or address mode of a unary operation. + */ char *ia32_emit_unop(const ir_node *n) { static char *buf = NULL; @@ -89,6 +98,9 @@ char *ia32_emit_unop(const ir_node *n) { return buf; } +/** + * Emits adressmode. + */ char *ia32_emit_am(const ir_node *n) { ia32_am_flavour_t am_flav = get_ia32_am_flavour(n); int had_output = 0; @@ -121,7 +133,7 @@ char *ia32_emit_am(const ir_node *n) { lc_eoprintf(ia32_get_arg_env(), obst, "%2S", n); if (am_flav & ia32_S) { - obstack_printf(obst, "*%d", get_ia32_am_scale(n)); + obstack_printf(obst, "*%d", 1 << get_ia32_am_scale(n)); } had_output = 1; @@ -229,13 +241,18 @@ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) { return arch_register_get_index(reg); } +enum io_direction { + IN_REG, + OUT_REG +}; + /** * Returns the name of the in register at position pos. */ -const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) { +static const char *get_ia32_reg_name(ir_node *irn, int pos, enum io_direction in_out) { const arch_register_t *reg; - if (in_out == 1) { + if (in_out == IN_REG) { reg = get_in_reg(irn, pos); } else { @@ -258,12 +275,7 @@ static int ia32_get_reg_name(lc_appendable_t *app, if (!X) return lc_arg_append(app, occ, "(null)", 6); - if (occ->conversion == 'S') { - buf = get_ia32_reg_name(X, nr, 1); - } - else { /* 'D' */ - buf = get_ia32_reg_name(X, nr, 0); - } + buf = get_ia32_reg_name(X, nr, occ->conversion == 'S' ? IN_REG : OUT_REG); lc_appendable_chadd(app, '%'); return lc_arg_append(app, occ, buf, strlen(buf)); @@ -762,77 +774,106 @@ void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) { ***********************************************************************************/ /** - * Emits code for a node. + * Enters the emitter functions for handled nodes into the generic + * pointer of an opcode. */ -void ia32_emit_node(ir_node *irn, void *env) { - emit_env_t *emit_env = env; - firm_dbg_module_t *mod = emit_env->mod; - FILE *F = emit_env->out; +void ia32_register_emitters(void) { + int i; - DBG((mod, LEVEL_1, "emitting code for %+F\n", irn)); +#define BEGIN() if (0) +#define IA32_EMIT(a) else if (op_ia32_##a == op) op->ops.generic = (op_func)emit_ia32_##a +#define EMIT(a) else if (op_##a == op) op->ops.generic = (op_func)emit_##a +#define END() else op->ops.generic = (op_func)NULL + + for (i = get_irp_n_opcodes() - 1; i >= 0; --i) { + ir_op *op = get_irp_opcode(i); + + BEGIN(); + /* generated int emitter functions */ + IA32_EMIT(Const); + + IA32_EMIT(Add); + IA32_EMIT(Sub); + IA32_EMIT(Minus); + IA32_EMIT(Inc); + IA32_EMIT(Dec); -#define IA32_EMIT(a) if (is_ia32_##a(irn)) { emit_ia32_##a(irn, emit_env); return; } -#define EMIT(a) if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; } + IA32_EMIT(Max); + IA32_EMIT(Min); + IA32_EMIT(CMov); - /* generated int emitter functions */ - IA32_EMIT(Const); + IA32_EMIT(And); + IA32_EMIT(Or); + IA32_EMIT(Eor); + IA32_EMIT(Not); - IA32_EMIT(Add); - IA32_EMIT(Sub); - IA32_EMIT(Minus); - IA32_EMIT(Inc); - IA32_EMIT(Dec); + IA32_EMIT(Shl); + IA32_EMIT(Shr); + IA32_EMIT(Shrs); + IA32_EMIT(RotL); + IA32_EMIT(RotR); - IA32_EMIT(Max); - IA32_EMIT(Min); - IA32_EMIT(CMov); + IA32_EMIT(Lea); - IA32_EMIT(And); - IA32_EMIT(Or); - IA32_EMIT(Eor); - IA32_EMIT(Not); + IA32_EMIT(Mul); - IA32_EMIT(Shl); - IA32_EMIT(Shr); - IA32_EMIT(Shrs); - IA32_EMIT(RotL); - IA32_EMIT(RotR); + IA32_EMIT(Cdq); + IA32_EMIT(DivMod); - IA32_EMIT(Lea); + IA32_EMIT(Store); + IA32_EMIT(Load); - IA32_EMIT(Mul); + IA32_EMIT(CopyB); + IA32_EMIT(CopyB_i); - IA32_EMIT(Cdq); - IA32_EMIT(DivMod); + /* generated floating point emitter */ + IA32_EMIT(fConst); - IA32_EMIT(Store); - IA32_EMIT(Load); + IA32_EMIT(fAdd); + IA32_EMIT(fSub); - IA32_EMIT(CopyB); - IA32_EMIT(CopyB_i); + IA32_EMIT(fMul); + IA32_EMIT(fDiv); - /* generated floating point emitter */ - IA32_EMIT(fConst); + IA32_EMIT(fMin); + IA32_EMIT(fMax); - IA32_EMIT(fAdd); - IA32_EMIT(fSub); + IA32_EMIT(fLoad); + IA32_EMIT(fStore); - IA32_EMIT(fMul); - IA32_EMIT(fDiv); + /* other emitter functions */ + IA32_EMIT(CondJmp); + IA32_EMIT(SwitchJmp); + IA32_EMIT(Call); - IA32_EMIT(fMin); - IA32_EMIT(fMax); + EMIT(Jmp); + EMIT(Proj); - IA32_EMIT(fLoad); - IA32_EMIT(fStore); + END(); + } - /* other emitter functions */ - IA32_EMIT(CondJmp); - IA32_EMIT(SwitchJmp); - IA32_EMIT(Call); +#undef BEGIN +#undef IA32_EMIT +#undef EMIT +#undef END + +} + +/** + * Emits code for a node. + */ +static void ia32_emit_node(ir_node *irn, void *env) { + emit_env_t *emit_env = env; + firm_dbg_module_t *mod = emit_env->mod; + FILE *F = emit_env->out; + ir_op *op = get_irn_op(irn); + + DBG((mod, LEVEL_1, "emitting code for %+F\n", irn)); - EMIT(Jmp); - EMIT(Proj); + if (op->ops.generic) { + void (*emit)(ir_node *, void *) = (void (*)(ir_node *, void *))op->ops.generic; + (*emit)(irn, env); + } ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn); } @@ -841,7 +882,7 @@ void ia32_emit_node(ir_node *irn, void *env) { * Walks over the nodes in a block connected by scheduling edges * and emits code for each node. */ -void ia32_gen_block(ir_node *block, void *env) { +static void ia32_gen_block(ir_node *block, void *env) { ir_node *irn; if (! is_Block(block)) @@ -891,7 +932,7 @@ void ia32_gen_labels(ir_node *block, void *env) { } /** - * Main driver + * Main driver. Emits the code for one routine. */ void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) { emit_env_t emit_env;