From 7c5ef5e313aea108a7e90764b7aa1a50e77894c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Mon, 20 Feb 2006 14:25:16 +0000 Subject: [PATCH] code refactoring for full addressmode support and more architecture independence --- ir/be/ia32/bearch_ia32.c | 57 +- ir/be/ia32/ia32_emitter.c | 62 +- ir/be/ia32/ia32_emitter.h | 4 +- ir/be/ia32/ia32_map_regs.c | 66 +- ir/be/ia32/ia32_new_nodes.c | 512 ++++++++++----- ir/be/ia32/ia32_new_nodes.h | 59 +- ir/be/ia32/ia32_nodes_attr.h | 45 +- ir/be/ia32/ia32_spec.pl | 650 ++++++++---------- ir/be/ia32/ia32_transform.c | 1193 ++++++++++++++++------------------ 9 files changed, 1331 insertions(+), 1317 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index ac7f6b3d5..40cfacf7b 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -41,6 +41,8 @@ static set *cur_reg_set = NULL; #undef is_Start #define is_Start(irn) (get_irn_opcode(irn) == iro_Start) +extern ir_node *be_new_NoReg(ir_graph *irg); + /************************************************** * _ _ _ __ * | | | (_)/ _| @@ -133,6 +135,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re assert(irn_req && "missing requirement for regparam"); memcpy(req, &(irn_req->req), sizeof(*req)); return req; + //return NULL; } else if (is_Proj(irn)) { if (pos == -1) { @@ -170,9 +173,9 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re if (is_Phi(irn)) { DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn)); if (mode_is_float(mode)) - memcpy(req, &(ia32_default_req_ia32_floating_point.req), sizeof(*req)); + memcpy(req, &(ia32_default_req_ia32_fp.req), sizeof(*req)); else if (mode_is_int(mode) || mode_is_reference(mode)) - memcpy(req, &(ia32_default_req_ia32_general_purpose.req), sizeof(*req)); + memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req)); else if (mode == mode_T || mode == mode_M) { DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn)); return NULL; @@ -195,7 +198,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re } else if (get_irn_op(irn) == op_Return && pos > 0) { DB((mod, LEVEL_1, "returning reqs EAX for %+F\n", irn)); - memcpy(req, &(ia32_default_req_ia32_general_purpose_eax.req), sizeof(*req)); + memcpy(req, &(ia32_default_req_ia32_gp_eax.req), sizeof(*req)); } else { DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn)); @@ -275,7 +278,7 @@ static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) { if (is_ia32_irn(irn)) return get_ia32_flags(irn); else { - if (is_Start_Proj(irn) || is_Unknown(irn)) + if (is_Start_Proj(irn)) return arch_irn_flags_ignore; return 0; @@ -337,7 +340,7 @@ static void ia32_prepare_graph(void *self) { irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &(cg->has_alloca)); if (cg->has_alloca) { - ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore; + ia32_gp_regs[REG_EBP].type = arch_register_type_ignore; } irg_walk_blkwise_graph(cg->irg, ia32_place_consts, ia32_transform_node, cg); @@ -350,6 +353,7 @@ static void ia32_prepare_graph(void *self) { * Stack reservation and StackParam lowering. */ static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) { +#if 0 firm_dbg_module_t *mod = cg->mod; ir_node *frame = get_irg_frame(irg); ir_node *end_block = get_irg_end_block(irg); @@ -363,10 +367,10 @@ static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) { /* Determine stack register */ if (cg->has_alloca) { - stack_reg = &ia32_general_purpose_regs[REG_EBP]; + stack_reg = &ia32_gp_regs[REG_EBP]; } else { - stack_reg = &ia32_general_purpose_regs[REG_ESP]; + stack_reg = &ia32_gp_regs[REG_ESP]; } /* If frame is used, then we need to reserve some stackspace. */ @@ -443,6 +447,7 @@ static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) { sched_add_after(sched_point, stack_free); } } +#endif } @@ -470,15 +475,18 @@ static ir_node *ia32_lower_spill(void *self, ir_node *spill) { ir_node *ptr = get_irg_frame(cg->irg); ir_node *val = be_get_Spill_context(spill); ir_node *mem = new_rd_NoMem(cg->irg); + ir_node *noreg = be_new_NoReg(cg->irg); ir_mode *mode = get_irn_mode(spill); ir_node *res; entity *ent = be_get_spill_entity(spill); unsigned offs = get_entity_offset_bytes(ent); + char buf[64]; DB((cg->mod, LEVEL_1, "lower_spill: got offset %d for %+F\n", offs, ent)); - res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, val, mem, mode); - set_ia32_am_offs(res, new_tarval_from_long(offs, mode_Iu)); + res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, noreg, val, mem, mode); + snprintf(buf, sizeof(buf), "%d", offs); + add_ia32_am_offs(res, buf); return res; } @@ -493,24 +501,29 @@ static ir_node *ia32_lower_reload(void *self, ir_node *reload) { ir_node *ptr = get_irg_frame(cg->irg); ir_mode *mode = get_irn_mode(reload); ir_node *pred = get_irn_n(reload, 0); - tarval *tv; + ir_node *noreg = be_new_NoReg(cg->irg); + char buf[64]; + char *ofs; ir_node *res; if (be_is_Spill(pred)) { entity *ent = be_get_spill_entity(pred); unsigned offs = get_entity_offset_bytes(ent); DB((cg->mod, LEVEL_1, "lower_reload: got offset %d for %+F\n", offs, ent)); - tv = new_tarval_from_long(offs, mode_Iu); + + snprintf(buf, sizeof(buf), "%d", offs); } else if (is_ia32_Store(pred)) { - tv = get_ia32_am_offs(pred); + ofs = get_ia32_am_offs(pred); + strncpy(buf, ofs, sizeof(buf)); + free(ofs); } else { assert(0 && "unsupported Reload predecessor"); } - res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, pred, mode); - set_ia32_am_offs(res, tv); + res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, noreg, pred, mode); + add_ia32_am_offs(res, buf); return res; } @@ -522,10 +535,10 @@ static const arch_register_t *ia32_get_stack_register(void *self) { ia32_code_gen_t *cg = self; if (cg->has_alloca) { - return &ia32_general_purpose_regs[REG_EBP]; + return &ia32_gp_regs[REG_EBP]; } - return &ia32_general_purpose_regs[REG_ESP]; + return &ia32_gp_regs[REG_ESP]; } /** @@ -543,7 +556,7 @@ static void ia32_codegen(void *self) { } ia32_finish_irg(irg, cg); - dump_ir_block_graph_sched(irg, "-finished"); + //dump_ir_block_graph_sched(irg, "-finished"); ia32_gen_routine(out, irg, cg); cur_reg_set = NULL; @@ -674,17 +687,17 @@ long ia32_handle_call_proj(const void *self, ir_node *proj, int is_keep) { assert(pn == 0 && "only one floating point result supported"); /* Get the proj number for the floating point result */ - pn = ia32_get_reg_projnum(&ia32_floating_point_regs[REG_XMM0], isa->reg_projnum_map); + pn = ia32_get_reg_projnum(&ia32_fp_regs[REG_XMM0], isa->reg_projnum_map); } else { /* In case of 64bit return value, the result is */ /* in EDX:EAX and we have two result projs. */ switch (pn) { case 0: - pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EAX], isa->reg_projnum_map); + pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EAX], isa->reg_projnum_map); break; case 1: - pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EDX], isa->reg_projnum_map); + pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EDX], isa->reg_projnum_map); break; default: assert(0 && "only two int results supported"); @@ -696,7 +709,7 @@ long ia32_handle_call_proj(const void *self, ir_node *proj, int is_keep) { } else { /* Set mode to floating point if required */ - if (!strcmp(ia32_reg_classes[CLASS_ia32_floating_point].name, + if (!strcmp(ia32_reg_classes[CLASS_ia32_fp].name, ia32_projnum_reg_req_map[pn]->req.cls->name)) { set_irn_mode(proj, mode_F); } @@ -722,7 +735,7 @@ list_sched_selector_t ia32_sched_selector; * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded */ static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) { - memcpy(&ia32_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t)); + memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t)); ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule; return &ia32_sched_selector; } diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index caf4f18a7..03907b420 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -25,6 +25,17 @@ static const arch_env_t *arch_env = NULL; +char *ia32_emit_binop(ir_node *irn) { + return "R1, R2"; +} + +char *ia32_emit_unop(ir_node *irn) { + return "R"; +} + +char *ia32_emit_am(ir_node *irn) { + return "AM"; +} /************************************************************* * _ _ __ _ _ @@ -41,35 +52,24 @@ static const arch_env_t *arch_env = NULL; * Return node's tarval as string. */ const char *node_const_to_str(ir_node *n) { - char *buf; - tarval *tv = get_ia32_Immop_tarval(n); + char *s = get_ia32_cnst(n); - if (tv) { - buf = xmalloc(SNPRINTF_BUF_LEN); - tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv); - return buf; - } - else if (get_ia32_old_ir(n)) { - return get_sc_name(get_ia32_old_ir(n)); - } - else - return "0"; + if (!s) + s = "NULL"; + + return s; } /** * Returns node's offset as string. */ char *node_offset_to_str(ir_node *n) { - char *buf; - tarval *tv = get_ia32_am_offs(n); + char *s = get_ia32_am_offs(n); - if (tv) { - buf = xmalloc(SNPRINTF_BUF_LEN); - tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv); - return buf; - } - else - return ""; + if (!s) + s = ""; + + return s; } /* We always pass the ir_node which is a pointer. */ @@ -736,15 +736,10 @@ void ia32_emit_node(ir_node *irn, void *env) { #define EMIT(a) if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; } /* generated int emitter functions */ - IA32_EMIT(Copy); - IA32_EMIT(Perm); - IA32_EMIT(Const); IA32_EMIT(Add); - IA32_EMIT(Add_i); IA32_EMIT(Sub); - IA32_EMIT(Sub_i); IA32_EMIT(Minus); IA32_EMIT(Inc); IA32_EMIT(Dec); @@ -753,30 +748,21 @@ void ia32_emit_node(ir_node *irn, void *env) { IA32_EMIT(Min); IA32_EMIT(And); - IA32_EMIT(And_i); IA32_EMIT(Or); - IA32_EMIT(Or_i); IA32_EMIT(Eor); - IA32_EMIT(Eor_i); IA32_EMIT(Not); IA32_EMIT(Shl); - IA32_EMIT(Shl_i); IA32_EMIT(Shr); - IA32_EMIT(Shr_i); IA32_EMIT(Shrs); - IA32_EMIT(Shrs_i); IA32_EMIT(RotL); - IA32_EMIT(RotL_i); IA32_EMIT(RotR); IA32_EMIT(Lea); - IA32_EMIT(Lea_i); IA32_EMIT(Mul); - IA32_EMIT(Mul_i); - IA32_EMIT(Cltd); + IA32_EMIT(Cdq); IA32_EMIT(DivMod); IA32_EMIT(Store); @@ -787,7 +773,6 @@ void ia32_emit_node(ir_node *irn, void *env) { IA32_EMIT(fAdd); IA32_EMIT(fSub); - IA32_EMIT(fMinus); IA32_EMIT(fMul); IA32_EMIT(fDiv); @@ -800,11 +785,8 @@ void ia32_emit_node(ir_node *irn, void *env) { /* other emitter functions */ IA32_EMIT(CondJmp); - IA32_EMIT(CondJmp_i); IA32_EMIT(SwitchJmp); IA32_EMIT(Call); - IA32_EMIT(Alloca); - IA32_EMIT(Alloca_i); EMIT(Jmp); EMIT(Proj); diff --git a/ir/be/ia32/ia32_emitter.h b/ir/be/ia32/ia32_emitter.h index 584b86464..3f529193c 100644 --- a/ir/be/ia32/ia32_emitter.h +++ b/ir/be/ia32/ia32_emitter.h @@ -18,7 +18,9 @@ typedef struct _emit_env_t { const lc_arg_env_t *ia32_get_arg_env(void); -void equalize_dest_src(FILE *F, ir_node *n); +char *ia32_emit_binop(ir_node *irn); +char *ia32_emit_unop(ir_node *irn); +char *ia32_emit_am(ir_node *irn); int get_ia32_reg_nr(ir_node *irn, int posi, int in_out); const char *get_ia32_in_reg_name(ir_node *irn, int pos); diff --git a/ir/be/ia32/ia32_map_regs.c b/ir/be/ia32/ia32_map_regs.c index 1173cedb7..745f7ab2d 100644 --- a/ir/be/ia32/ia32_map_regs.c +++ b/ir/be/ia32/ia32_map_regs.c @@ -18,44 +18,44 @@ static int maxnum_fpreg_args = 5; /* maximum number of float arguments passed /* this is the order of the assigned registers usesd for parameter passing */ const ia32_register_req_t *gpreg_param_req_std[] = { - &ia32_default_req_ia32_general_purpose_eax, - &ia32_default_req_ia32_general_purpose_ecx, - &ia32_default_req_ia32_general_purpose_edx, - &ia32_default_req_ia32_general_purpose_ebx, - &ia32_default_req_ia32_general_purpose_edi, - &ia32_default_req_ia32_general_purpose_esi + &ia32_default_req_ia32_gp_eax, + &ia32_default_req_ia32_gp_ecx, + &ia32_default_req_ia32_gp_edx, + &ia32_default_req_ia32_gp_ebx, + &ia32_default_req_ia32_gp_edi, + &ia32_default_req_ia32_gp_esi }; const ia32_register_req_t *gpreg_param_req_this[] = { - &ia32_default_req_ia32_general_purpose_ecx, - &ia32_default_req_ia32_general_purpose_eax, - &ia32_default_req_ia32_general_purpose_edx, - &ia32_default_req_ia32_general_purpose_ebx, - &ia32_default_req_ia32_general_purpose_edi, - &ia32_default_req_ia32_general_purpose_esi + &ia32_default_req_ia32_gp_ecx, + &ia32_default_req_ia32_gp_eax, + &ia32_default_req_ia32_gp_edx, + &ia32_default_req_ia32_gp_ebx, + &ia32_default_req_ia32_gp_edi, + &ia32_default_req_ia32_gp_esi }; const ia32_register_req_t *fpreg_param_req_std[] = { - &ia32_default_req_ia32_floating_point_xmm0, - &ia32_default_req_ia32_floating_point_xmm1, - &ia32_default_req_ia32_floating_point_xmm2, - &ia32_default_req_ia32_floating_point_xmm3, - &ia32_default_req_ia32_floating_point_xmm4, - &ia32_default_req_ia32_floating_point_xmm5, - &ia32_default_req_ia32_floating_point_xmm6, - &ia32_default_req_ia32_floating_point_xmm7 + &ia32_default_req_ia32_fp_xmm0, + &ia32_default_req_ia32_fp_xmm1, + &ia32_default_req_ia32_fp_xmm2, + &ia32_default_req_ia32_fp_xmm3, + &ia32_default_req_ia32_fp_xmm4, + &ia32_default_req_ia32_fp_xmm5, + &ia32_default_req_ia32_fp_xmm6, + &ia32_default_req_ia32_fp_xmm7 }; const ia32_register_req_t *fpreg_param_req_this[] = { NULL, /* in case of a "this" pointer, the first parameter must not be a float */ - &ia32_default_req_ia32_floating_point_xmm0, - &ia32_default_req_ia32_floating_point_xmm1, - &ia32_default_req_ia32_floating_point_xmm2, - &ia32_default_req_ia32_floating_point_xmm3, - &ia32_default_req_ia32_floating_point_xmm4, - &ia32_default_req_ia32_floating_point_xmm5, - &ia32_default_req_ia32_floating_point_xmm6, - &ia32_default_req_ia32_floating_point_xmm7 + &ia32_default_req_ia32_fp_xmm0, + &ia32_default_req_ia32_fp_xmm1, + &ia32_default_req_ia32_fp_xmm2, + &ia32_default_req_ia32_fp_xmm3, + &ia32_default_req_ia32_fp_xmm4, + &ia32_default_req_ia32_fp_xmm5, + &ia32_default_req_ia32_fp_xmm6, + &ia32_default_req_ia32_fp_xmm7 }; @@ -247,13 +247,13 @@ long ia32_translate_proj_pos(const ir_node *proj) { else if (is_ia32_Store(pred)) { return 0; } - else if (is_ia32_CondJmp(pred) || is_ia32_CondJmp_i(pred)) { + else if (is_ia32_CondJmp(pred)) { return 0; } else if (is_ia32_SwitchJmp(pred)) { return 0; } - else if (is_ia32_Cltd(pred) || is_ia32_Mul(pred)) { + else if (is_ia32_Cdq(pred) || is_ia32_Mulh(pred)) { if (nr == pn_EAX) return 0; if (nr == pn_EDX) @@ -265,6 +265,12 @@ long ia32_translate_proj_pos(const ir_node *proj) { if (nr == pn_DivMod_res_mod || pn_Mod_res) return 1; } + else if (is_ia32_fDiv(pred)) { + if (nr == pn_Quot_res) + return 0; + else + assert(0 && "there should be no more Projs for a fDiv"); + } else if (is_ia32_Call(pred)) { return 0; } diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index fe05c63fc..1182017a6 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -9,6 +9,12 @@ #include "config.h" #endif +#ifdef _WIN32 +#include +#else +#include +#endif + #include #include "irprog_t.h" @@ -20,6 +26,7 @@ #include "irop.h" #include "firm_common_t.h" #include "irvrfy_t.h" +#include "irprintf.h" #include "../bearch.h" @@ -27,7 +34,13 @@ #include "ia32_new_nodes.h" #include "gen_ia32_regalloc_if.h" - +#ifdef obstack_chunk_alloc +# undef obstack_chunk_alloc +# define obstack_chunk_alloc xmalloc +#else +# define obstack_chunk_alloc xmalloc +# define obstack_chunk_free free +#endif /*********************************************************************************** * _ _ _ __ @@ -79,6 +92,81 @@ const char *get_sc_name(ir_node *symc) { return NULL; } +/** + * Returns a string containing the names of all registers within the limited bitset + */ +static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) { + bitset_t *bs = bitset_alloca(req->cls->n_regs); + char *p = buf; + int size = 0; + int i, cnt; + + req->limited(NULL, bs); + + for (i = 0; i < req->cls->n_regs; i++) { + if (bitset_is_set(bs, i)) { + cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name); + if (cnt < 0) { + fprintf(stderr, "dumper problem, exiting\n"); + exit(1); + } + + p += cnt; + size += cnt; + + if (size >= max) + break; + } + } + + return buf; +} + +/** + * Dumps the register requirements for either in or out. + */ +static void dump_reg_req(FILE *F, ir_node *n, const ia32_register_req_t **reqs, int inout) { + char *dir = inout ? "out" : "in"; + int max = inout ? get_ia32_n_res(n) : get_irn_arity(n); + char *buf = alloca(1024); + int i; + + memset(buf, 0, 1024); + + if (reqs) { + for (i = 0; i < max; i++) { + fprintf(F, "%sreq #%d =", dir, i); + + if (reqs[i]->req.type == arch_register_req_type_none) { + fprintf(F, " n/a"); + } + + if (reqs[i]->req.type & arch_register_req_type_normal) { + fprintf(F, " %s", reqs[i]->req.cls->name); + } + + if (reqs[i]->req.type & arch_register_req_type_limited) { + fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024)); + } + + if (reqs[i]->req.type & arch_register_req_type_should_be_same) { + ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->pos)); + } + + if (reqs[i]->req.type & arch_register_req_type_should_be_different) { + ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->pos)); + } + + fprintf(F, "\n"); + } + + fprintf(F, "\n"); + } + else { + fprintf(F, "%sreq = N/A\n", dir); + } +} + /** * Dumper interface for dumping ia32 nodes in vcg. * @param n the node to dump @@ -87,18 +175,16 @@ const char *get_sc_name(ir_node *symc) { * @return 0 on success or != 0 on failure */ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { - const char *name, *p; - ir_mode *mode = NULL; - int bad = 0; - asmop_attr *attr; - int i; + ir_mode *mode = NULL; + int bad = 0; + int i; + ia32_attr_t *attr; const ia32_register_req_t **reqs; const arch_register_t **slots; switch (reason) { case dump_node_opcode_txt: - name = get_irn_opname(n); - fprintf(F, "%s", name); + fprintf(F, "%s", get_irn_opname(n)); break; case dump_node_mode_txt: @@ -108,7 +194,7 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { mode = NULL; } else if (is_ia32_Load(n)) { - mode = get_irn_mode(get_irn_n(n, 1)); + mode = get_irn_mode(get_irn_n(n, 0)); } else if (is_ia32_Store(n)) { mode = get_irn_mode(get_irn_n(n, 2)); @@ -120,70 +206,39 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { break; case dump_node_nodeattr_txt: - name = get_irn_opname(n); - p = name + strlen(name) - 2; - if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) { - tarval *tv = get_ia32_Immop_tarval(n); - if (tv) { - fprintf_tv(F, tv, 1); - } - else { - fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n))); - } + if (is_ia32_Call(n)) { + fprintf(F, "&%s ", get_ia32_sc(n)); } - else if (is_ia32_Call(n)) { - ir_node *sc = get_ia32_old_ir(n); + else if (get_ia32_cnst(n)) { + char *pref = ""; - fprintf(F, "&%s ", get_sc_name(sc)); + if (get_ia32_sc(n)) { + pref = "SymC "; + } + + fprintf(F, "[%s%s]", pref, get_ia32_cnst(n)); } - if (is_ia32_AddrMode(n)) { - fprintf(F, "[AddrMode] "); + if (is_ia32_AddrModeS(n) || is_ia32_AddrModeD(n)) { + fprintf(F, "[AM] "); } break; case dump_node_info_txt: attr = get_ia32_attr(n); + fprintf(F, "=== IA32 attr begin ===\n"); /* dump IN requirements */ if (get_irn_arity(n) > 0) { reqs = get_ia32_in_req_all(n); - - if (reqs) { - for (i = 0; i < get_irn_arity(n); i++) { - if (reqs[i]->req.type != arch_register_req_type_none) { - fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->req.cls->name); - } - else { - fprintf(F, "inreq[%d]=[none]\n", i); - } - } - - fprintf(F, "\n"); - } - else { - fprintf(F, "NO IN REQS\n"); - } + dump_reg_req(F, n, reqs, 0); } /* dump OUT requirements */ if (attr->n_res > 0) { reqs = get_ia32_out_req_all(n); - - if (reqs) { - for (i = 0; i < attr->n_res; i++) { - if (reqs[i]->req.type != arch_register_req_type_none) { - fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->req.cls->name); - } - else { - fprintf(F, "outreq[%d]=[none]\n", i); - } - } - } - else { - fprintf(F, "NO OUT REQS\n"); - } + dump_reg_req(F, n, reqs, 1); } /* dump assigned registers */ @@ -198,29 +253,82 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { } } } + fprintf(F, "\n"); + + /* dump op type */ + fprintf(F, "op = "); + switch (attr->tp) { + case ia32_Normal: + fprintf(F, "Normal"); + break; + case ia32_Const: + fprintf(F, "Const"); + break; + case ia32_SymConst: + fprintf(F, "SymConst"); + break; + case ia32_AddrModeD: + fprintf(F, "AM Dest (Load+Store)"); + break; + case ia32_AddrModeS: + fprintf(F, "AM Source (Load)"); + break; + } + fprintf(F, "\n"); + + + /* dump supported am */ + fprintf(F, "AM support = "); + switch (attr->am_support) { + case ia32_am_None: + fprintf(F, "none"); + break; + case ia32_am_Source: + fprintf(F, "source only (Load)"); + break; + case ia32_am_Dest: + fprintf(F, "dest only (Load+Store)"); + break; + case ia32_am_Full: + fprintf(F, "full"); + break; + } + fprintf(F, "\n"); - /* special for LEA */ - if (is_ia32_Lea(n) || is_ia32_Lea_i(n)) { - tarval *o = get_ia32_am_offs(n); - tarval *tv = get_ia32_Immop_tarval(n); + /* dump AM offset */ + fprintf(F, "AM offset = "); + if (attr->am_offs) { + fprintf(F, "%s", get_ia32_am_offs(n)); + } + else { + fprintf(F, "n/a"); + } + fprintf(F, "\n"); - fprintf(F, "LEA "); - if (o) { - fprintf_tv(F, o, 0); - } + /* dump AM scale */ + fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n)); - fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0))); + /* dump pn code */ + fprintf(F, "pn_code = %d\n", get_ia32_pncode(n)); - if (is_ia32_Lea(n)) { - fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1))); - } + /* dump n_res */ + fprintf(F, "n_res = %d\n", get_ia32_n_res(n)); - if (tv) { - fprintf(F, ", "); - fprintf_tv(F, tv, 0); - } - fprintf(F, ")\n"); + /* dump flags */ + fprintf(F, "flags ="); + if (attr->flags & arch_irn_flags_dont_spill) { + fprintf(F, " unspillable"); + } + if (attr->flags & arch_irn_flags_rematerializable) { + fprintf(F, " remat"); + } + if (attr->flags & arch_irn_flags_ignore) { + fprintf(F, " ignore"); } + fprintf(F, "\n"); + + fprintf(F, "=== IA32 attr end ===\n"); + /* end of: case dump_node_info_txt */ break; } @@ -240,84 +348,136 @@ static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) { * |___/ ***************************************************************************************************/ + static char *copy_str(char *dst, const char *src) { + dst = xcalloc(1, strlen(src) + 1); + strncpy(dst, src, strlen(src) + 1); + return dst; + } + + static char *set_cnst_from_tv(char *cnst, tarval *tv) { + if (cnst) { + free(cnst); + } + + cnst = xcalloc(1, 64); + assert(tarval_snprintf(cnst, 63, tv)); + return cnst; + } + /** * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast. * Firm was made by people hating const :-( */ -asmop_attr *get_ia32_attr(const ir_node *node) { +ia32_attr_t *get_ia32_attr(const ir_node *node) { assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes"); - return (asmop_attr *)get_irn_generic_attr((ir_node *)node); + return (ia32_attr_t *)get_irn_generic_attr((ir_node *)node); } /** * Gets the type of an ia32 node. */ -asmop_type_t get_ia32_op_type(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); +ia32_op_type_t get_ia32_op_type(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); return attr->tp; } /** * Sets the type of an ia32 node. */ -void set_ia32_op_type(const ir_node *node, asmop_type_t tp) { - asmop_attr *attr = get_ia32_attr(node); - attr->tp = tp; +void set_ia32_op_type(ir_node *node, ia32_op_type_t tp) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->tp = tp; } /** - * Gets the addr mode type of an ia32 node + * Gets the supported addrmode of an ia32 node */ -addrmode_type_t get_ia32_am_type(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - return attr->am_tp; +ia32_am_type_t get_ia32_am_support(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return attr->am_support; } /** - * Sets the addr mode type of an ia32 node + * Sets the supported addrmode of an ia32 node */ -void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp) { - asmop_attr *attr = get_ia32_attr(node); - attr->am_tp = am_tp; +void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->am_support = am_tp; } /** - * Gets the addr mode offset. + * Joins all offsets to one string with adds. */ -tarval *get_ia32_am_offs(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - return attr->am_offs; +char *get_ia32_am_offs(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + char *res = NULL; + int size; + + size = obstack_object_size(attr->am_offs); + if (size > 0) { + res = xcalloc(1, size + 1); + memcpy(res, obstack_base(attr->am_offs), size); + } + + res[size] = '\0'; + return res; } /** - * Sets the offset for addr mode. + * Add an offset for addrmode. */ -void set_ia32_am_offs(ir_node *node, tarval *am_offs) { - asmop_attr *attr = get_ia32_attr(node); - attr->am_offs = am_offs; +static void extend_ia32_am_offs(ir_node *node, char *offset, char op) { + ia32_attr_t *attr = get_ia32_attr(node); + + if (!attr->am_offs) { + /* obstack is not initialized */ + attr->am_offs = xcalloc(1, sizeof(*(attr->am_offs))); + obstack_init(attr->am_offs); + } + else { + /* obstack is initialized -> there is already one offset */ + /* present -> connect the offsets with an add */ + obstack_printf(attr->am_offs, " %c ", op); + } + + obstack_printf(attr->am_offs, "%s", offset); +} + +/** + * Add an offset for addrmode. + */ +void add_ia32_am_offs(ir_node *node, char *offset) { + extend_ia32_am_offs(node, offset, '+'); +} + +/** + * Sub an offset for addrmode. + */ +void sub_ia32_am_offs(ir_node *node, char *offset) { + extend_ia32_am_offs(node, offset, '-'); } /** * Gets the addr mode const. */ -tarval *get_ia32_am_const(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - return attr->am_const; +int get_ia32_am_scale(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return attr->am_scale; } /** - * Sets the const for addr mode. + * Sets the index register scale for addrmode. */ -void set_ia32_am_const(ir_node *node, tarval *am_const) { - asmop_attr *attr = get_ia32_attr(node); - attr->am_const = am_const; +void set_ia32_am_scale(ir_node *node, int scale) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->am_scale = scale; } /** * Return the tarval of an immediate operation or NULL in case of SymConst */ tarval *get_ia32_Immop_tarval(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->tv; } @@ -325,31 +485,45 @@ tarval *get_ia32_Immop_tarval(const ir_node *node) { * Sets the attributes of an immediate operation to the specified tarval */ void set_ia32_Immop_tarval(ir_node *node, tarval *tv) { - asmop_attr *attr = get_ia32_attr(node); - attr->tv = tv; + ia32_attr_t *attr = get_ia32_attr(node); + attr->tv = tv; + attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv); +} + +/** + * Return the sc attribute. + */ +char *get_ia32_sc(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return attr->sc; } /** - * Return the old_ir attribute. + * Sets the sc attribute. */ -ir_node *get_ia32_old_ir(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - return attr->old_ir; +void set_ia32_sc(ir_node *node, char *sc) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->sc = copy_str(attr->sc, sc); + + if (attr->cnst) { + free(attr->cnst); + } + attr->cnst = attr->sc; } /** - * Sets the old_ir attribute. + * Gets the string representation of the internal const (tv or symconst) */ -void set_ia32_old_ir(ir_node *node, ir_node *old_ir) { - asmop_attr *attr = get_ia32_attr(node); - attr->old_ir = old_ir; +char *get_ia32_cnst(ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return attr->cnst; } /** * Returns the argument register requirements of an ia32 node. */ const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->in_req; } @@ -357,7 +531,7 @@ const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) { * Returns the result register requirements of an ia32 node. */ const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->out_req; } @@ -365,7 +539,7 @@ const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) { * Returns the argument register requirement at position pos of an ia32 node. */ const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->in_req[pos]; } @@ -373,7 +547,7 @@ const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) { * Returns the result register requirement at position pos of an ia32 node. */ const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->out_req[pos]; } @@ -381,7 +555,7 @@ const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) { * Sets the OUT register requirements at position pos. */ void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); attr->out_req[pos] = req; } @@ -389,7 +563,7 @@ void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) { * Sets the IN register requirements at position pos. */ void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); attr->in_req[pos] = req; } @@ -397,7 +571,7 @@ void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) { * Returns the register flag of an ia32 node. */ arch_irn_flags_t get_ia32_flags(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->flags; } @@ -405,15 +579,15 @@ arch_irn_flags_t get_ia32_flags(const ir_node *node) { * Sets the register flag of an ia32 node. */ void set_ia32_flags(const ir_node *node, arch_irn_flags_t flags) { - asmop_attr *attr = get_ia32_attr(node); - attr->flags = flags; + ia32_attr_t *attr = get_ia32_attr(node); + attr->flags = flags; } /** * Returns the result register slots of an ia32 node. */ const arch_register_t **get_ia32_slots(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->slots; } @@ -421,7 +595,7 @@ const arch_register_t **get_ia32_slots(const ir_node *node) { * Returns the name of the OUT register at position pos. */ const char *get_ia32_out_reg_name(const ir_node *node, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < attr->n_res && "Invalid OUT position."); @@ -434,7 +608,7 @@ const char *get_ia32_out_reg_name(const ir_node *node, int pos) { * Returns the index of the OUT register at position pos within its register class. */ int get_ia32_out_regnr(const ir_node *node, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < attr->n_res && "Invalid OUT position."); @@ -447,7 +621,7 @@ int get_ia32_out_regnr(const ir_node *node, int pos) { * Returns the OUT register at position pos. */ const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); assert(is_ia32_irn(node) && "Not an ia32 node."); assert(pos < attr->n_res && "Invalid OUT position."); @@ -460,39 +634,39 @@ const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) { * Sets the number of results. */ void set_ia32_n_res(ir_node *node, int n_res) { - asmop_attr *attr = get_ia32_attr(node); - attr->n_res = n_res; + ia32_attr_t *attr = get_ia32_attr(node); + attr->n_res = n_res; } /** * Returns the number of results. */ int get_ia32_n_res(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->n_res; } /** * Returns the flavour of an ia32 node, */ -op_flavour_t get_ia32_flavour(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); +ia32_op_flavour_t get_ia32_flavour(const ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); return attr->op_flav; } /** * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh. */ -void set_ia32_flavour(ir_node *node, op_flavour_t op_flav) { - asmop_attr *attr = get_ia32_attr(node); - attr->op_flav = op_flav; +void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->op_flav = op_flav; } /** * Returns the projnum code. */ long get_ia32_pncode(const ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); return attr->pn_code; } @@ -500,8 +674,8 @@ long get_ia32_pncode(const ir_node *node) { * Sets the projnum code */ void set_ia32_pncode(ir_node *node, long code) { - asmop_attr *attr = get_ia32_attr(node); - attr->pn_code = code; + ia32_attr_t *attr = get_ia32_attr(node); + attr->pn_code = code; } @@ -520,7 +694,7 @@ void set_ia32_pncode(ir_node *node, long code) { * Gets the type of an ia32_Const. */ unsigned get_ia32_Const_type(ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type"); @@ -531,10 +705,10 @@ unsigned get_ia32_Const_type(ir_node *node) { * Sets the type of an ia32_Const. */ void set_ia32_Const_type(ir_node *node, int type) { - asmop_attr *attr = get_ia32_attr(node); + ia32_attr_t *attr = get_ia32_attr(node); assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type"); - assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type"); + assert((type == ia32_Const || type == ia32_SymConst) && "Unsupported ia32_Const type"); attr->tp = type; } @@ -543,20 +717,19 @@ void set_ia32_Const_type(ir_node *node, int type) { * Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node */ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) { - asmop_attr *na = get_ia32_attr(node); - asmop_attr *ca = get_ia32_attr(cnst); + ia32_attr_t *na = get_ia32_attr(node); + ia32_attr_t *ca = get_ia32_attr(cnst); assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr"); na->tp = ca->tp; na->tv = ca->tv; - if (ca->old_ir) { - na->old_ir = xcalloc(1, sizeof(*(ca->old_ir))); - memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir))); + if (ca->sc) { + na->sc = copy_str(na->sc, ca->sc); } else { - na->old_ir = NULL; + na->sc = NULL; } } @@ -564,20 +737,21 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) { * Copy the attributes from a Const to an ia32_Const */ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) { - asmop_attr *attr = get_ia32_attr(ia32_cnst); + ia32_attr_t *attr = get_ia32_attr(ia32_cnst); assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr"); switch (get_irn_opcode(cnst)) { case iro_Const: - attr->tp = asmop_Const; - attr->tv = get_Const_tarval(cnst); + attr->tp = ia32_Const; + attr->tv = get_Const_tarval(cnst); + attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv); break; case iro_SymConst: - attr->tp = asmop_SymConst; - attr->tv = NULL; - attr->old_ir = xcalloc(1, sizeof(*cnst)); - memcpy(attr->old_ir, cnst, sizeof(*cnst)); + attr->tp = ia32_SymConst; + attr->tv = NULL; + attr->sc = copy_str(attr->sc, get_sc_name(cnst)); + attr->cnst = attr->sc; break; case iro_Unknown: assert(0 && "Unknown Const NYI"); @@ -588,19 +762,37 @@ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) { } /** - * Sets the AddrMode attribute + * Sets the AddrMode(S|D) attribute + */ +void set_ia32_AddrMode(ir_node *node, char direction) { + ia32_attr_t *attr = get_ia32_attr(node); + + switch (direction) { + case 'D': + attr->tp = ia32_AddrModeD; + break; + case 'S': + attr->tp = ia32_AddrModeS; + break; + default: + assert(0 && "wrong AM type"); + } +} + +/** + * Returns whether or not the node is an AddrModeS node. */ -void set_ia32_AddrMode(ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - attr->tp = asmop_AddrMode; +int is_ia32_AddrModeS(ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return (attr->tp == ia32_AddrModeS); } /** - * Returns whether or not the node is an AddrMode node. + * Returns whether or not the node is an AddrModeD node. */ -int is_ia32_AddrMode(ir_node *node) { - asmop_attr *attr = get_ia32_attr(node); - return (attr->tp == asmop_AddrMode); +int is_ia32_AddrModeD(ir_node *node) { + ia32_attr_t *attr = get_ia32_attr(node); + return (attr->tp == ia32_AddrModeD); } diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index 5b3478d80..c0b4b26c5 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -30,47 +30,52 @@ const char *get_sc_name(ir_node *symc); /** * Returns the attributes of an ia32 node. */ -asmop_attr *get_ia32_attr(const ir_node *node); +ia32_attr_t *get_ia32_attr(const ir_node *node); /** * Gets the type of an ia32 node. */ -asmop_type_t get_ia32_op_type(const ir_node *node); +ia32_op_type_t get_ia32_op_type(const ir_node *node); /** * Sets the type of an ia32 node. */ -void set_ia32_op_type(const ir_node *node, asmop_type_t tp); +void set_ia32_op_type(ir_node *node, ia32_op_type_t tp); /** - * Gets the addr mode type of an ia32 node + * Gets the supported addrmode of an ia32 node */ -addrmode_type_t get_ia32_am_type(const ir_node *node); +ia32_am_type_t get_ia32_am_support(const ir_node *node); /** - * Sets the addr mode type of an ia32 node + * Sets the supported addrmode of an ia32 node */ -void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp); +void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp); /** - * Gets the addr mode offset. + * Gets the joined addrmode offset. */ -tarval *get_ia32_am_offs(const ir_node *node); +char *get_ia32_am_offs(const ir_node *node); /** - * Sets the offset for addr mode. + * Adds an offset for addrmode. */ -void set_ia32_am_offs(ir_node *node, tarval *am_offs); +void add_ia32_am_offs(ir_node *node, char *offset); + +/** + * Subs an offset for addrmode. + */ +void sub_ia32_am_offs(ir_node *node, char *offset); /** * Gets the addr mode const. */ -tarval *get_ia32_am_const(const ir_node *node); +int get_ia32_am_scale(const ir_node *node); /** * Sets the const for addr mode. */ -void set_ia32_am_const(ir_node *node, tarval *am_const); +void set_ia32_am_scale(ir_node *node, int scale); /** * Return the tarval of an immediate operation or NULL in case of SymConst @@ -83,14 +88,19 @@ tarval *get_ia32_Immop_tarval(const ir_node *node); void set_ia32_Immop_tarval(ir_node *node, tarval *tv); /** - * Return the old_ir attribute. + * Return the sc attribute. + */ +char *get_ia32_sc(const ir_node *node); + +/** + * Sets the sc attribute. */ -ir_node *get_ia32_old_ir(const ir_node *node); +void set_ia32_sc(ir_node *node, char *sc); /** - * Sets the old_ir attribute. + * Gets the string representation of the internal const (tv or symconst) */ -void set_ia32_old_ir(ir_node *node, ir_node *old_ir); +char *get_ia32_cnst(ir_node *node); /** * Returns the argument register requirements of an ia32 node. @@ -165,12 +175,12 @@ int get_ia32_n_res(const ir_node *node); /** * Returns the flavour of an ia32 node, */ -op_flavour_t get_ia32_flavour(const ir_node *node); +ia32_op_flavour_t get_ia32_flavour(const ir_node *node); /** * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh. */ -void set_ia32_flavour(ir_node *node, op_flavour_t op_flav); +void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav); /** * Returns the projnum code. @@ -217,18 +227,19 @@ void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst); /** * Sets the AddrMode attribute + * @param direction The "direction" of AM ('S' source or 'D' destination) */ -void set_ia32_AddrMode(ir_node *node); +void set_ia32_AddrMode(ir_node *node, char direction); /** - * Returns whether or not the node is an AddrMode node. + * Returns whether or not the node is an AddrModeS node. */ -int is_ia32_AddrMode(ir_node *node); +int is_ia32_AddrModeS(ir_node *node); /** - * Checks whether or not an ir_node is an ia32 node + * Returns whether or not the node is an AddrModeD node. */ -int is_ia32_irn(const ir_node *node); +int is_ia32_AddrModeD(ir_node *node); /* Include the generated headers */ #include "gen_ia32_new_nodes.h" diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 653f53dea..9c7e7e72d 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -1,47 +1,46 @@ #ifndef _IA32_NODES_ATTR_H_ #define _IA32_NODES_ATTR_H_ +#include + #include "firm_types.h" #include "../bearch.h" -typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } op_flavour_t; +typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } ia32_op_flavour_t; typedef enum { pn_EAX, pn_EDX } pn_ia32_Register; -typedef enum { asmop_Normal, asmop_Const, asmop_SymConst, asmop_AddrMode } asmop_type_t; +typedef enum { ia32_Normal, ia32_Const, ia32_SymConst, ia32_AddrModeD, ia32_AddrModeS } ia32_op_type_t; typedef enum { - am_Reg = 1, /**<< (%reg) */ - am_OffsReg, /**<< o(%reg) */ - am_RegReg, /**<< (%reg, %reg) */ - am_RegConst, /**<< ( , %reg, const) */ - am_OffsRegConst, /**<< o( , %reg, const) */ - am_OffsRegReg, /**<< o(%reg, %reg) */ - am_RegRegConst, /**<< (%reg, %reg, const) */ - am_OffsRegRegConst /**<< o(%reg, %reg, const) */ -} addrmode_type_t; + ia32_am_None = 0, /**<< no addrmode support */ + ia32_am_Dest = 1, /**<< addrmode for destination only */ + ia32_am_Source = 2, /**<< addrmode for source only */ + ia32_am_Full = 3 /**<< full addmode support */ +} ia32_am_type_t; typedef struct _ia32_register_req_t { const arch_register_req_t req; int pos; /**<< in case of "should be same/different" we need to remember the pos to get the irn */ } ia32_register_req_t; -typedef struct _ia32_asmop_attr { - asmop_type_t tp; /**<< ia32 node type */ - addrmode_type_t am_tp; /**<< addr mode type */ +typedef struct _ia32_attr_t { + ia32_op_type_t tp; /**<< ia32 node type */ + ia32_am_type_t am_support; /**<< indicates addrmode type supported by this node */ - tarval *am_offs; /**<< offset for AddrMode */ - tarval *am_const; /**<< shift const for AddrMode */ + struct obstack *am_offs; /**<< offsets for AddrMode */ + int am_scale; /**<< addrmode scale for index register */ - tarval *tv; /**<< tarval for immediate operations */ - ir_node *old_ir; /**<< old ir node to avoid duplicating information (symconst in case of asmop_SymConst) */ + tarval *tv; /**<< tarval for immediate operations */ + char *sc; /**<< symconst name */ + char *cnst; /**<< points to the string representation of the constant value (either tv or sc) */ - op_flavour_t op_flav; /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */ - long pn_code; /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */ - long n_res; /**<< number of results */ - arch_irn_flags_t flags; /**<< indicating if spillable and/or rematerializeable */ + ia32_op_flavour_t op_flav; /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */ + long pn_code; /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */ + long n_res; /**<< number of results */ + arch_irn_flags_t flags; /**<< indicating if spillable and/or rematerializeable */ const ia32_register_req_t **in_req; /**<< register requirements for arguments */ const ia32_register_req_t **out_req; /**<< register requirements for results */ const arch_register_t **slots; /**<< register slots for assigned registers */ -} asmop_attr; +} ia32_attr_t; #endif /* _IA32_NODES_ATTR_H_ */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 3b5c14d5c..a23a2c7c9 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -12,15 +12,17 @@ $arch = "ia32"; # %nodes = ( # # => { -# "op_flags" => "N|L|C|X|I|F|Y|H|c|K", -# "arity" => "0|1|2|3|variable|dynamic|all", -# "state" => "floats|pinned", -# "args" => [ -# { "type" => "type 1", "name" => "name 1" }, -# { "type" => "type 2", "name" => "name 2" }, -# ... -# ], -# "comment" => "any comment for constructor", +# "op_flags" => "N|L|C|X|I|F|Y|H|c|K", +# "irn_flags" => "R|N|I" +# "arity" => "0|1|2|3 ... |variable|dynamic|all", +# "state" => "floats|pinned", +# "args" => [ +# { "type" => "type 1", "name" => "name 1" }, +# { "type" => "type 2", "name" => "name 2" }, +# ... +# ], +# "comment" => "any comment for constructor", +# "emit" => "emit code with templates", # "rd_constructor" => "c source code which constructs an ir_node" # }, # @@ -28,6 +30,7 @@ $arch = "ia32"; # # ); # close the %nodes initializer +# op_flags: flags for the operation, OPTIONAL (default is "N") # the op_flags correspond to the firm irop_flags: # N irop_flag_none # L irop_flag_labeled @@ -40,7 +43,11 @@ $arch = "ia32"; # c irop_flag_constlike # K irop_flag_keep # -# op_flags: flags for the operation, OPTIONAL (default is "N") +# irn_flags: special node flags, OPTIONAL (default is 0) +# following irn_flags are supported: +# R rematerializeable +# N not spillable +# I ignore for register allocation # # state: state of the operation, OPTIONAL (default is "pinned") # @@ -81,26 +88,27 @@ $arch = "ia32"; # caller save registers and in the correct order, otherwise it will break # the magic! %reg_classes = ( - "general_purpose" => [ - { "name" => "eax", "type" => 2 }, - { "name" => "edx", "type" => 2 }, - { "name" => "ebx", "type" => 3 }, - { "name" => "ecx", "type" => 2 }, - { "name" => "esi", "type" => 3 }, - { "name" => "edi", "type" => 3 }, - { "name" => "ebp", "type" => 3 }, - { "name" => "esp", "type" => 4 } # we don't want esp to be assigned - ], - "floating_point" => [ - { "name" => "xmm0", "type" => 2 }, - { "name" => "xmm1", "type" => 2 }, - { "name" => "xmm2", "type" => 2 }, - { "name" => "xmm3", "type" => 2 }, - { "name" => "xmm4", "type" => 2 }, - { "name" => "xmm5", "type" => 2 }, - { "name" => "xmm6", "type" => 2 }, - { "name" => "xmm7", "type" => 2 }, - ] + "gp" => [ + { "name" => "eax", "type" => 2 }, + { "name" => "edx", "type" => 2 }, + { "name" => "ebx", "type" => 3 }, + { "name" => "ecx", "type" => 2 }, + { "name" => "esi", "type" => 3 }, + { "name" => "edi", "type" => 3 }, + { "name" => "ebp", "type" => 3 }, + { "name" => "esp", "type" => 4 }, # we don't want esp to be assigned + { "name" => "xxx", "type" => 4 } # we need a dummy register for NoReg and Unknown nodes + ], + "fp" => [ + { "name" => "xmm0", "type" => 2 }, + { "name" => "xmm1", "type" => 2 }, + { "name" => "xmm2", "type" => 2 }, + { "name" => "xmm3", "type" => 2 }, + { "name" => "xmm4", "type" => 2 }, + { "name" => "xmm5", "type" => 2 }, + { "name" => "xmm6", "type" => 2 }, + { "name" => "xmm7", "type" => 2 } + ] ); # %reg_classes #--------------------------------------------------# @@ -129,144 +137,90 @@ $arch = "ia32"; # commutative operations -"Add" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. addl %S2, %D1\t\t\t/* Add(%S1, %S2) -> %D1, (%A1, %A2) */' -}, +# NOTE: +# All nodes supporting Addressmode have 5 INs: +# 1 - base r1 == NoReg in case of no AM or no base +# 2 - index r2 == NoReg in case of no AM or no index +# 3 - op1 r3 == always present +# 4 - op2 r4 == NoReg in case of immediate operation +# 5 - mem NoMem in case of no AM otherwise it takes the mem from the Load -"Add_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. addl %C, %D1\t\t\t/* Add(%C, %S1) -> %D1, (%A1, const) */' +"Add" => { + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. add %ia32_emit_binop\t\t\t/* Add(%A1, %A2) -> %D1 */' }, "Mul" => { - "op_flags" => "C", - "arity" => 2, - "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "eax in_r1", "edx in_r2" ] }, - "emit" => -' if (mode_is_signed(get_irn_mode(n))) { -4. imull %S2\t\t\t/* signed Mul(%S1, %S2) -> %D1, (%A1, %A2) */ - } - else { -4. mull %S2\t\t\t/* unsigned Mul(%S1, %S2) -> %D1, (%A1, %A2) */ - } -' + "op_flags" => "C", + "irn_flags" => "A", + "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. imul %ia32_emit_binop\t\t\t/* Mul(%A1, %A2) -> %D1 */' }, -"Mul_i" => { - "state" => "pinned", - "arity" => 1, - "comment" => "construct Mul: Mul(a, const) = Mul(const, a) = a * const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] }, - "emit" => -' if (mode_is_signed(get_irn_mode(n))) { -4. imull %C\t\t\t/* signed Mul(%C, %S1) -> %D1, (%A1, const) */ - } - else { -4. mull %C\t\t\t/* unsigned Mul(%C, %S1) -> %D1, (%A1, const) */ - } -' +# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX +"Mulh" => { + "op_flags" => "C", + "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r2" ] }, + "emit" => '. imul %ia32_emit_unop\t\t\t/* Mulh(%A1, %A2) -> %D1 */ ' }, "And" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct And: And(a, b) = And(b, a) = a AND b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. andl %S2, %D1\t\t\t/* And(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"And_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct And: And(a, const) = And(const, a) = a AND const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. andl %C, %D1\t\t\t/* And(%C, %S1) -> %D1, (%A1, const) */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct And: And(a, b) = And(b, a) = a AND b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. and %ia32_emit_binop\t\t\t/* And(%A1, %A2) -> %D1 */' }, "Or" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. orl %S2, %D1\t\t\t/* Or(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Or_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. orl %C, %D1\t\t\t/* Or(%C, %S1) -> %D1, (%A1, const) */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. or %ia32_emit_binop\t\t\t/* Or(%A1, %A2) -> %D1 */' }, "Eor" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. xorl %S2, %D1\t\t\t/* Xor(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Eor_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. xorl %C, %D1\t\t\t/* Xor(%C, %S1) -> %D1, (%A1, const) */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. xor %ia32_emit_binop\t\t\t/* Xor(%A1, %A2) -> %D1 */' }, "Max" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => -'2. cmpl %S2, %S1\t\t\t/* prepare Max (%S1 should be %D1), (%A1, %A2) */ + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b", + "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, + "emit" => +'2. cmp %S1, %S2\t\t\t/* prepare Max (%S1 - %S2), (%A1, %A2) */ if (mode_is_signed(get_irn_mode(n))) { -4. cmovl %S2, %D1\t\t\t/* %S1 is less %S2 */ +4. cmovl %D1, %S2\t\t\t/* %S1 is less %S2 */ } else { -4. cmovb %S2, %D1\t\t\t/* %S1 is below %S2 */ +4. cmovb %D1, %S2\t\t\t/* %S1 is below %S2 */ } ' }, "Min" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "comment" => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => -'2. cmpl %S2, %S1\t\t\t/* prepare Min (%S1 should be %D1), (%A1, %A2) */ + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b", + "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, + "emit" => +'2. cmp %S1, %S2\t\t\t/* prepare Min (%S1 - %S2), (%A1, %A2) */ if (mode_is_signed(get_irn_mode(n))) { -2. cmovg %S2, %D1\t\t\t/* %S1 is greater %S2 */ +2. cmovg %D1, %S2\t\t\t/* %S1 is greater %S2 */ } else { -2. cmova %S2, %D1\t\t\t/* %S1 is above %S2 */ +2. cmova %D1, %S2, %D1\t\t\t/* %S1 is above %S2 */ } ' }, @@ -274,202 +228,128 @@ $arch = "ia32"; # not commutative operations "Sub" => { - "arity" => 2, - "remat" => 1, - "comment" => "construct Sub: Sub(a, b) = a - b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. subl %S2, %D1\t\t\t/* Sub(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Sub_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Sub: Sub(a, const) = a - const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. subl %C, %D1\t\t\t/* Sub(%S1, %C) -> %D1, (%A1, const) */' + "irn_flags" => "R", + "comment" => "construct Sub: Sub(a, b) = a - b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. sub %ia32_emit_binop\t\t\t/* Sub(%A1, %A2) -> %D1 */' }, "DivMod" => { - "op_flags" => "F|L", - "state" => "exc_pinned", - "arity" => 4, - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "general_purpose", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] }, - "emit" => + "op_flags" => "F|L", + "state" => "exc_pinned", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] }, + "emit" => ' if (mode_is_signed(get_irn_mode(n))) { -4. idivl %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */ +4. idiv %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */ } else { -4. divl %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */ +4. div %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */ } ' }, "Shl" => { - "arity" => 2, - "remat" => 1, - "comment" => "construct Shl: Shl(a, b) = a << b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. shll %S2, %D1\t\t\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shl_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Shl: Shl(a, const) = a << const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. shll %C, %D1\t\t\t/* Shl(%S1, %C) -> %D1, (%A1, const) */' + "irn_flags" => "R", + "comment" => "construct Shl: Shl(a, b) = a << b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. shl %ia32_emit_binop\t\t\t/* Shl(%A1, %A2) -> %D1 */' }, "Shr" => { - "arity" => 2, - "remat" => 1, - "comment" => "construct Shr: Shr(a, b) = a >> b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. shrl %S2, %D1\t\t\t/* Shr(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shr_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Shr: Shr(a, const) = a >> const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. shrl %C, %D1\t\t\t/* Shr(%S1, %C) -> %D1, (%A1, const) */' + "irn_flags" => "R", + "comment" => "construct Shr: Shr(a, b) = a >> b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. shr %ia32_emit_binop\t\t\t/* Shr(%A1, %A2) -> %D1 */' }, "Shrs" => { - "arity" => 2, - "remat" => 1, - "comment" => "construct Shrs: Shrs(a, b) = a >> b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. sarl %S2, %D1\t\t\t/* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shrs_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Shrs: Shrs(a, const) = a >> const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. sarl %C, %D1\t\t\t/* Shrs(%S1, %C) -> %D1, (%A1, const) */' + "irn_flags" => "R", + "comment" => "construct Shrs: Shrs(a, b) = a >> b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. sar %ia32_emit_binop\t\t\t/* Shrs(%A1, %A2) -> %D1 */' }, "RotR" => { - "arity" => 2, - "remat" => 1, + "irn_flags" => "R", "comment" => "construct RotR: RotR(a, b) = a ROTR b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. rorl %S2, %D1\t\t\t/* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. ror %ia32_emit_binop\t\t\t/* RotR(%A1, %A2) -> %D1 */' }, "RotL" => { - "arity" => 2, - "remat" => 1, - "comment" => "construct RotL: RotL(a, b) = a ROTL b", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. roll %S2, %D1\t\t\t/* RotL(%S1, %S2) -> %D1, (%A1, %A2) */' + "irn_flags" => "R", + "comment" => "construct RotL: RotL(a, b) = a ROTL b", + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. rol %ia32_emit_binop\t\t\t/* RotL(%A1, %A2) -> %D1 */' }, -"RotL_i" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct RotL: RotL(a, const) = a ROTL const", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. roll %C, %D1\t\t\t/* RotL(%S1, %C) -> %D1, (%A1, const) */' -}, +# unary operations "Minus" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Minus: Minus(a) = -a", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. negl %D1\t\t\t/* Neg(%S1) -> %D1, (%A1) */' + "irn_flags" => "R", + "comment" => "construct Minus: Minus(a) = -a", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. neg %ia32_emit_unop\t\t\t/* Neg(%A1) -> %D1, (%A1) */' }, "Inc" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Increment: Inc(a) = a++", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. incl %D1\t\t\t/* Inc(%S1) -> %D1, (%A1) */' + "irn_flags" => "R", + "comment" => "construct Increment: Inc(a) = a++", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. inc %ia32_emit_unop\t\t\t/* Inc(%S1) -> %D1, (%A1) */' }, "Dec" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Decrement: Dec(a) = a--", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. decl %D1\t\t\t/* Dec(%S1) -> %D1, (%A1) */' + "irn_flags" => "R", + "comment" => "construct Decrement: Dec(a) = a--", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. dec %ia32_emit_unop\t\t\t/* Dec(%S1) -> %D1, (%A1) */' }, "Not" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Not: Not(a) = !a", - "check_inout" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. notl %D1\t\t\t/* Not(%S1) -> %D1, (%A1) */' + "irn_flags" => "R", + "comment" => "construct Not: Not(a) = !a", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. not %ia32_emit_unop\t\t\t/* Not(%S1) -> %D1, (%A1) */' }, # other operations "Conv" => { "arity" => 1, - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] }, + "reg_req" => { "in" => [ "gp" ], "out" => [ "in_r1" ] }, "comment" => "construct Conv: Conv(a) = (conv)a" }, "CondJmp" => { - "op_flags" => "C|L|X|Y", - "arity" => 2, - "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] }, -}, - -"CondJmp_i" => { - "op_flags" => "L|X|Y", - "arity" => 1, - "comment" => "construct conditional jump: CMP A, const && JMPxx LABEL", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "none", "none" ] }, + "op_flags" => "C|L|X|Y", + "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] }, }, "SwitchJmp" => { - "op_flags" => "L|X|Y", - "arity" => 1, - "comment" => "construct switch", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "none" ] }, + "op_flags" => "L|X|Y", + "comment" => "construct switch", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, }, "Const" => { - "op_flags" => "c", - "arity" => "0", - "remat" => 1, - "comment" => "represents an integer constant", - "reg_req" => { "out" => [ "general_purpose" ] }, - "emit" => '. movl %C, %D1\t\t\t/* Mov Const into register */', - "cmp_attr" => + "op_flags" => "c", + "irn_flags" => "R", + "comment" => "represents an integer constant", + "reg_req" => { "out" => [ "gp" ] }, + "emit" => '. mov %D1, %C\t\t\t/* Mov Const into register */', + "cmp_attr" => ' if (attr_a->tp == attr_b->tp) { - if (attr_a->tp == asmop_SymConst) { - if (attr_a->old_ir == NULL || attr_b->old_ir == NULL) + if (attr_a->tp == ia32_SymConst) { + if (attr_a->sc == NULL || attr_b->sc == NULL) return 1; else - return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir)); + return strcmp(attr_a->sc, attr_b->sc); } else { - if (attr_a->old_ir == NULL || attr_b->old_ir == NULL) + if (attr_a->tv == NULL || attr_b->tv == NULL) return 1; if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq) @@ -483,55 +363,44 @@ $arch = "ia32"; ' }, -"Cltd" => { - "arity" => 1, - "remat" => 1, - "comment" => "construct Cltd: sign extend EAX -> EDX:EAX", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] }, - "emit" => '. cltd\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */' +"Cdq" => { + "irn_flags" => "R", + "comment" => "construct CDQ: sign extend EAX -> EDX:EAX", + "reg_req" => { "in" => [ "gp" ], "out" => [ "eax in_r1", "edx" ] }, + "emit" => '. cdq\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */' }, # Load / Store "Load" => { - "op_flags" => "L|F", - "state" => "exc_pinned", - "arity" => 2, - "remat" => 1, - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. movl %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1, (%A1) */' + "op_flags" => "L|F", + "irn_flags" => "R", + "state" => "exc_pinned", + "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", + "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] }, + "emit" => '. mov %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */' }, "Store" => { - "op_flags" => "L|F", - "state" => "exc_pinned", - "arity" => 3, - "remat" => 1, - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' + "op_flags" => "L|F", + "state" => "exc_pinned", + "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", + "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] }, + "emit" => '. mov %ia32_emit_am, %S3\t\t\t/* Store(%A2) -> (%A1) */' }, "Lea" => { - "arity" => 2, - "comment" => "construct Lea: Lea(a,b) = lea offs(a,b,const) | res = a + b * const + offs with const = 0,1,2,4,8", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. leal %O(%S1, %S2, %C), %D1\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */' -}, - -"Lea_i" => { - "arity" => 1, - "comment" => "construct Lea: Lea(a) = lea offs(a) | res = a + offs", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. leal %C(%S1), %D1\t\t\t/* %D1 = %S1 + %C, (%A1)*/' + "irn_flags" => "R", + "comment" => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8", + "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, + "emit" => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */' }, "StackParam" => { "arity" => 1, "remat" => 1, "comment" => "constructs a Stack Parameter to retrieve a parameter from Stack", - "reg_req" => { "in" => [ "none" ], "out" => [ "general_purpose" ] }, + "reg_req" => { "in" => [ "none" ], "out" => [ "gp" ] }, "cmp_attr" => ' return (attr_a->pn_code != attr_b->pn_code); @@ -541,7 +410,7 @@ $arch = "ia32"; "StackArg" => { "arity" => 2, "comment" => "constructs a Stack Argument to pass an argument on Stack", - "reg_req" => { "in" => [ "none", "general_purpose" ], "out" => [ "none" ] }, + "reg_req" => { "in" => [ "none", "gp" ], "out" => [ "none" ] }, "cmp_attr" => ' return (attr_a->pn_code != attr_b->pn_code); @@ -560,106 +429,108 @@ $arch = "ia32"; # commutative operations "fAdd" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" => '. add%M %S2, %D1\t\t\t/* SSE Add(%S1, %S2) -> %D1 */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A1, %A2) -> %D1 */' }, "fMul" => { - "op_flags" => "C", - "arity" => 2, - "check_inout" => 1, - "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" =>'. muls%M %S2, %D1\t\t\t/* SSE Mul(%S1, %S2) -> %D1 */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A1, %A2) -> %D1 */' }, "fMax" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" =>'. maxs%M %S2, %D1\t\t\t/* SSE Max(%S1, %S2) -> %D1 */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A1, %A2) -> %D1 */' }, "fMin" => { - "op_flags" => "C", - "arity" => 2, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" =>'. mins%M %S2, %D1\t\t\t/* SSE Min(%S1, %S2) -> %D1 */' + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A1, %A2) -> %D1 */' +}, + +"fAnd" => { + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE And: And(a, b) = a AND b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. andp%M %ia32_emit_binop\t\t\t/* SSE And(%A3, %A4) -> %D1 */' +}, + +"fOr" => { + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Or: Or(a, b) = a OR b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. orp%M %ia32_emit_binop\t\t\t/* SSE Or(%A3, %A4) -> %D1 */' +}, + +"fEor" => { + "op_flags" => "C", + "irn_flags" => "R", + "comment" => "construct SSE Eor: Eor(a, b) = a XOR b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] }, + "emit" => '. xorp%M %ia32_emit_binop\t\t\t/* SSE Xor(%A3, %A4) -> %D1 */' }, # not commutative operations "fSub" => { - "arity" => 2, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" => '. subs%M %S2, %D1\t\t\t/* SSE Sub(%S1, %S2) -> %D1 */' + "irn_flags" => "R", + "comment" => "construct SSE Sub: Sub(a, b) = a - b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. subs%M %ia32_emit_binop\t\t\t/* SSE Sub(%A1, %A2) -> %D1 */' }, "fDiv" => { - "arity" => 2, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] }, - "emit" => '. divs%M %S2, %D1\t\t\t/* SSE Div(%S1, %S2) -> %D1 */' -}, - -"fMinus" => { - "arity" => 1, - "remat" => 1, - "check_inout" => 1, - "comment" => "construct SSE Minus: Minus(a) = -a", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "in_r1" ] }, - "emit" => '. xorp%M c %D1\t\t\t/* SSE Minus(%S1) -> %D1 */' + "irn_flags" => "R", + "comment" => "construct SSE Div: Div(a, b) = a / b", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] }, + "emit" => '. divs%M %ia32_emit_binop\t\t\t/* SSE Div(%A1, %A2) -> %D1 */' }, # other operations "fConv" => { "arity" => 1, - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "general_purpose" ] }, + "reg_req" => { "in" => [ "fp" ], "out" => [ "gp" ] }, "comment" => "construct Conv: Conv(a) = (conv)a" }, "fCondJmp" => { - "op_flags" => "C|L|X|Y", - "arity" => 2, - "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] }, + "op_flags" => "C|L|X|Y", + "comment" => "construct conditional jump: UCOMIS A, B && JMPxx LABEL", + "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "none", "none" ] }, }, "fConst" => { - "op_flags" => "c", - "arity" => "0", - "remat" => 1, - "comment" => "represents a SSE constant", - "reg_req" => { "out" => [ "floating_point" ] }, - "emit" => '. mov%M %C, %D1\t\t\t/* Mov fConst into register */', - "cmp_attr" => + "op_flags" => "c", + "irn_flags" => "R", + "comment" => "represents a SSE constant", + "reg_req" => { "out" => [ "fp" ] }, + "emit" => '. mov%M %D1, %C\t\t\t/* Load fConst into register */', + "cmp_attr" => ' if (attr_a->tp == attr_b->tp) { - if (attr_a->tp == asmop_SymConst) { - if (attr_a->old_ir == NULL || attr_b->old_ir == NULL) + if (attr_a->tp == ia32_SymConst) { + if (attr_a->sc == NULL || attr_b->sc == NULL) return 1; else - return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir)); + return strcmp(attr_a->sc, attr_b->sc); } else { - if (attr_a->old_ir == NULL || attr_b->old_ir == NULL) + if (attr_a->tv == NULL || attr_b->tv == NULL) return 1; if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq) @@ -676,30 +547,27 @@ $arch = "ia32"; # Load / Store "fLoad" => { - "op_flags" => "L|F", - "state" => "exc_pinned", - "arity" => 2, - "remat" => 1, - "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] }, - "emit" => '. movl O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */' + "op_flags" => "L|F", + "irn_flags" => "R", + "state" => "exc_pinned", + "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr", + "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "fp" ] }, + "emit" => '. movs%M %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */' }, "fStore" => { "op_flags" => "L|F", "state" => "exc_pinned", - "arity" => 3, - "remat" => 1, "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "floating_point", "none" ] }, - "emit" => '. movl %S2, O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' + "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ] }, + "emit" => '. movs%M %ia32_emit_am, %S3\t\t\t/* Store(%S3) -> (%A1) */' }, "fStackParam" => { "arity" => 1, "remat" => 1, "comment" => "constructs a Stack Parameter to retrieve a SSE parameter from Stack", - "reg_req" => { "in" => [ "none" ], "out" => [ "floating_point" ] }, + "reg_req" => { "in" => [ "none" ], "out" => [ "fp" ] }, "cmp_attr" => ' return (attr_a->pn_code != attr_b->pn_code); @@ -709,7 +577,7 @@ $arch = "ia32"; "fStackArg" => { "arity" => 2, "comment" => "constructs a Stack Argument to pass an argument on Stack", - "reg_req" => { "in" => [ "none", "floating_point" ], "out" => [ "none" ] }, + "reg_req" => { "in" => [ "none", "fp" ], "out" => [ "none" ] }, "cmp_attr" => ' return (attr_a->pn_code != attr_b->pn_code); @@ -757,15 +625,7 @@ $arch = "ia32"; "state" => "pinned", "arity" => "2", "comment" => "construct Alloca: allocate memory on Stack", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] } + "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] } }, -"Alloca_i" => { - "op_flags" => "L|F", - "state" => "pinned", - "arity" => "1", - "comment" => "construct Alloca: allocate memory on Stack", - "reg_req" => { "out" => [ "general_purpose" ] } -} - ); # end of %nodes diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 37099db24..3eba47c3d 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -26,7 +26,16 @@ extern ir_op *get_op_Mulh(void); +typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ + ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode); +typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ + ir_node *op, ir_node *mem, ir_mode *mode); + +/* TEMPORARY WORKAROUND */ +ir_node *be_new_NoReg(ir_graph *irg) { + return new_NoMem(); +} /**************************************************************************************************** * _ _ __ _ _ @@ -38,18 +47,189 @@ extern ir_op *get_op_Mulh(void); * ****************************************************************************************************/ - +#undef is_cnst +#define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op)) /* determine if one operator is an Imm */ static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) { if (op1) - return is_ia32_Const(op1) ? op1 : (is_ia32_Const(op2) ? op2 : NULL); - else return is_ia32_Const(op2) ? op2 : NULL; + return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL); + else return is_cnst(op2) ? op2 : NULL; } /* determine if one operator is not an Imm */ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) { - return !is_ia32_Const(op1) ? op1 : (!is_ia32_Const(op2) ? op2 : NULL); + return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL); +} + + +/** + * Construct a standard binary operation, set AM and immediate if required. + * + * @param env The transformation environment + * @param op1 The first operand + * @param op2 The second operand + * @param func The node constructor function + * @return The constructed ia32 node. + */ +static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) { + ir_node *new_op = NULL; + ir_mode *mode = env->mode; + dbg_info *dbg = env->dbg; + ir_graph *irg = env->irg; + ir_node *block = env->block; + firm_dbg_module_t *mod = env->mod; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + ir_node *expr_op, *imm_op; + + + /* check if it's an operation with immediate */ + if (is_op_commutative(get_irn_op(env->irn))) { + imm_op = get_immediate_op(op1, op2); + expr_op = get_expr_op(op1, op2); + } + else { + imm_op = get_immediate_op(NULL, op2); + expr_op = get_expr_op(op1, op2); + } + + assert((expr_op || imm_op) && "invalid operands"); + + if (!expr_op) { + /* We have two consts here: not yet supported */ + imm_op = NULL; + } + + if (mode_is_float(mode)) { + /* floating point operations */ + if (imm_op) { + + new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T); + set_ia32_Immop_attr(new_op, imm_op); + set_ia32_am_support(new_op, ia32_am_None); + } + else { + new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T); + set_ia32_am_support(new_op, ia32_am_Source); + } + } + else { + /* integer operations */ + if (imm_op) { + /* This is expr + const */ + new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T); + set_ia32_Immop_attr(new_op, imm_op); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Dest); + } + else { + /* This is a normal operation */ + new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Full); + } + } + + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); +} + + + +/** + * Construct a shift/rotate binary operation, sets AM and immediate if required. + * + * @param env The transformation environment + * @param op1 The first operand + * @param op2 The second operand + * @param func The node constructor function + * @return The constructed ia32 node. + */ +static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) { + ir_node *new_op = NULL; + ir_mode *mode = env->mode; + dbg_info *dbg = env->dbg; + ir_graph *irg = env->irg; + ir_node *block = env->block; + firm_dbg_module_t *mod = env->mod; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + ir_node *expr_op, *imm_op; + tarval *tv; + + assert(! mode_is_float(mode) && "Shift/Rotate with float not supported"); + + imm_op = get_immediate_op(NULL, op2); + expr_op = get_expr_op(op1, op2); + + assert((expr_op || imm_op) && "invalid operands"); + + if (!expr_op) { + /* We have two consts here: not yet supported */ + imm_op = NULL; + } + + /* Limit imm_op within range imm8 */ + if (imm_op) { + tv = get_ia32_Immop_tarval(imm_op); + + if (tv) { + tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu)); + } + else { + imm_op = NULL; + } + } + + /* integer operations */ + if (imm_op) { + /* This is shift/rot with const */ + + new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T); + set_ia32_Immop_attr(new_op, imm_op); + } + else { + /* This is a normal shift/rot */ + new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T); + } + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Dest); + + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); +} + + +/** + * Construct a standard unary operation, set AM and immediate if required. + * + * @param env The transformation environment + * @param op The operand + * @param func The node constructor function + * @return The constructed ia32 node. + */ +static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) { + ir_node *new_op = NULL; + ir_mode *mode = env->mode; + dbg_info *dbg = env->dbg; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + + new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T); + + if (mode_is_float(mode)) { + /* floating point operations don't support implicit store */ + set_ia32_am_support(new_op, ia32_am_None); + } + else { + set_ia32_am_support(new_op, ia32_am_Dest); + } + + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -57,22 +237,23 @@ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) { /** * Creates an ia32 Add with immediate. * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Add_i node + * @param env The transformation environment + * @param expr_op The expression operator + * @param const_op The constant + * @return the created ia32 Add node */ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - ir_node *new_op; - tarval *tv = get_ia32_Immop_tarval(const_op); - int normal_add = 0; + ir_node *new_op = NULL; + tarval *tv = get_ia32_Immop_tarval(const_op); + firm_dbg_module_t *mod = env->mod; + dbg_info *dbg = env->dbg; + ir_mode *mode = env->mode; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + int normal_add = 1; tarval_classification_t class_tv, class_negtv; - firm_dbg_module_t *mod = env->mod; - dbg_info *dbg = env->dbg; - ir_mode *mode = env->mode; - ir_graph *irg = env->irg; - ir_node *block = env->block; /* const_op: tarval or SymConst? */ if (tv) { @@ -82,20 +263,20 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */ DB((env->mod, LEVEL_2, "Add(1) to Inc ... ")); - new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode); + new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T); + normal_add = 0; } else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */ DB((mod, LEVEL_2, "Add(-1) to Dec ... ")); - new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode); + new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T); + normal_add = 0; } - else - normal_add = 1; } - else - normal_add = 1; - if (normal_add) - new_op = new_rd_ia32_Lea_i(dbg, irg, block, expr_op, mode); + if (normal_add) { + new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T); + set_ia32_Immop_attr(new_op, const_op); + } return new_op; } @@ -111,128 +292,59 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node * @return the created ia32 Add node */ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - ir_node *shli_op; - ir_node *expr_op; - ir_node *new_op; - int normal_add = 0; - dbg_info *dbg = env->dbg; - ir_mode *mode = env->mode; - ir_graph *irg = env->irg; - ir_node *block = env->block; + ir_node *new_op = NULL; + dbg_info *dbg = env->dbg; + ir_mode *mode = env->mode; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + ir_node *expr_op, *imm_op; + + imm_op = get_immediate_op(op1, op2); + expr_op = get_expr_op(op1, op2); + + assert((expr_op || imm_op) && "invalid operands"); if (mode_is_float(mode)) { - return new_rd_ia32_fAdd(dbg, irg, block, op1, op2, mode); + return gen_binop(env, op1, op2, new_rd_ia32_fAdd); } - - /* try to optimize with LEA */ - - shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL); - expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL); - - if (shli_op) { - tarval *tv = get_ia32_Immop_tarval(shli_op); - tarval *offs = NULL; - if (tv) { - switch (get_tarval_long(tv)) { - case 1: - case 2: - case 3: - // If the other operand of the LEA is an LEA_i (that means LEA ofs(%regop1)), - // we can skip it and transform the whole sequence into LEA ofs(%regop1, %regop2, shl_val), - if (is_ia32_Lea_i(expr_op)) { - offs = get_ia32_Immop_tarval(expr_op); - expr_op = get_irn_n(expr_op, 0); - } - - new_op = new_rd_ia32_Lea(dbg, irg, block, expr_op, get_irn_n(shli_op, 0), mode); - set_ia32_Immop_tarval(new_op, tv); - set_ia32_am_offs(new_op, offs); - - break; - default: - normal_add = 1; - break; - } + else { + /* integer ADD */ + if (!expr_op) { + /* No expr_op means, that we have two const - one symconst and */ + /* one tarval or another symconst - because this case is not */ + /* covered by constant folding */ + + new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T); + add_ia32_am_offs(new_op, get_ia32_cnst(op1)); + add_ia32_am_offs(new_op, get_ia32_cnst(op2)); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Source); + set_ia32_op_type(new_op, ia32_AddrModeS); } - else - normal_add = 1; - } - else - normal_add = 1; - - if (normal_add) { - new_op = new_rd_ia32_Lea(dbg, irg, block, op1, op2, mode); - set_ia32_Immop_tarval(new_op, get_tarval_null(mode_Iu)); - set_ia32_am_offs(new_op, NULL); - } + else if (imm_op) { + /* This is expr + const */ + new_op = gen_imm_Add(env, expr_op, imm_op); - return new_op; -} - - - -/** - * Generates an ia32 Mul node. - * - * @param env The transformation environment - * @param op1 The first faktor - * @param op2 The second factor - * @param mul_flav flavour_Mul/Mulh - * @return The ready-to-go Mul node - */ -ir_node *generate_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, op_flavour_t mul_flav, int is_imm_op) { - ir_node *in_keep[1], *res; - long pn_good, pn_bad; - dbg_info *dbg = env->dbg; - ir_graph *irg = env->irg; - ir_node *block = env->block; - ir_mode *mode = env->mode; - ir_node *mul; - - /* create the mul */ - if (is_imm_op) { - mul = new_rd_ia32_Mul_i(dbg, irg, block, op1, mode_T); - set_ia32_Immop_attr(mul, op2); - } - else { - mul = new_rd_ia32_Mul(dbg, irg, block, op1, op2, mode_T); - } - set_ia32_flavour(mul, mul_flav); + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Dest); + } + else { + /* This is a normal add */ + new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T); - /* create the mul infrastructure */ - if (mul_flav == flavour_Mul) { - pn_good = pn_EAX; - pn_bad = pn_EDX; - } - else { /* Mulh */ - pn_good = pn_EDX; - pn_bad = pn_EAX; + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Full); + } } - res = new_rd_Proj(dbg, irg, block, mul, mode, pn_good); - in_keep[0] = new_rd_Proj(dbg, irg, block, mul, mode, pn_bad); - - be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep); - - return res; + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } -/** - * Creates an ia32 Mul with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Mul_i node - */ -static ir_node *gen_imm_Mul(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - /* Mul with immediate only possible with int, so we don't need to check for float */ - return generate_Mul(env, expr_op, const_op, flavour_Mul, 1); -} - /** * Creates an ia32 Mul. * @@ -244,132 +356,114 @@ static ir_node *gen_imm_Mul(ia32_transform_env_t *env, ir_node *expr_op, ir_node * @return the created ia32 Mul node */ ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { + ir_node *new_op; + if (mode_is_float(env->mode)) { - return new_rd_ia32_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode); + new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul); } else { - return generate_Mul(env, op1, op2, flavour_Mul, 0); + new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul); } -} + return new_op; +} -/** - * Creates an ia32 Mulh with immediate. - * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of - * this result while Mul returns the lower 32 bit. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Mulh_i node - */ -static ir_node *gen_imm_Mulh(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return generate_Mul(env, expr_op, const_op, flavour_Mulh, 1); -} /** * Creates an ia32 Mulh. * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of * this result while Mul returns the lower 32 bit. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator * @return the created ia32 Mulh node */ static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return generate_Mul(env, op1, op2, flavour_Mulh, 0); -} + ir_node *proj_EAX, *proj_EDX, *mulh; + ir_node *in[1]; + assert(mode_is_float(env->mode) && "Mulh with float not supported"); + proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh); + mulh = get_Proj_pred(proj_EAX); + proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX); + /* to be on the save side */ + set_Proj_proj(proj_EAX, pn_EAX); -/** - * Creates an ia32 And with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 And_i node - */ -static ir_node *gen_imm_And(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_And_i(env->dbg, env->irg, env->block, expr_op, env->mode); + if (get_ia32_cnst(mulh)) { + /* Mulh with const cannot have AM */ + set_ia32_am_support(mulh, ia32_am_None); + } + else { + /* Mulh cannot have AM for destination */ + set_ia32_am_support(mulh, ia32_am_Source); + } + + in[0] = proj_EAX; + + /* keep EAX */ + be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in); + + return proj_EDX; } + + /** * Creates an ia32 And. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 And node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 And node */ static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_And(env->dbg, env->irg, env->block, op1, op2, env->mode); + if (mode_is_float(env->mode)) { + return gen_binop(env, op1, op2, new_rd_ia32_fAnd); + } + else { + return gen_binop(env, op1, op2, new_rd_ia32_And); + } } -/** - * Creates an ia32 Or with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Or_i node - */ -static ir_node *gen_imm_Or(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_Or_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 Or. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Or node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Or node */ static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Or(env->dbg, env->irg, env->block, op1, op2, env->mode); + if (mode_is_float(env->mode)) { + return gen_binop(env, op1, op2, new_rd_ia32_fOr); + } + else { + return gen_binop(env, op1, op2, new_rd_ia32_Or); + } } -/** - * Creates an ia32 Eor with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Eor_i node - */ -static ir_node *gen_imm_Eor(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_Eor_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 Eor. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Eor node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Eor node */ static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode); + if (mode_is_float(env->mode)) { + return gen_binop(env, op1, op2, new_rd_ia32_fEor); + } + else { + return gen_binop(env, op1, op2, new_rd_ia32_Eor); + } } @@ -377,14 +471,23 @@ static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { /** * Creates an ia32 Max. * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Max node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return the created ia32 Max node */ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode); + ir_node *new_op; + + if (mode_is_float(env->mode)) { + new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax); + } + else { + new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode); + set_ia32_am_support(new_op, ia32_am_None); + } + + return new_op; } @@ -392,14 +495,23 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { /** * Creates an ia32 Min. * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Min node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return the created ia32 Min node */ static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode); + ir_node *new_op; + + if (mode_is_float(env->mode)) { + new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin); + } + else { + new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode); + set_ia32_am_support(new_op, ia32_am_None); + } + + return new_op; } @@ -407,22 +519,23 @@ static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { /** * Creates an ia32 Sub with immediate. * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Sub_i node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Sub node */ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - ir_node *new_op; - tarval *tv = get_ia32_Immop_tarval(const_op); - int normal_sub = 0; + ir_node *new_op = NULL; + tarval *tv = get_ia32_Immop_tarval(const_op); + firm_dbg_module_t *mod = env->mod; + dbg_info *dbg = env->dbg; + ir_mode *mode = env->mode; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + int normal_sub = 1; tarval_classification_t class_tv, class_negtv; - firm_dbg_module_t *mod = env->mod; - dbg_info *dbg = env->dbg; - ir_mode *mode = env->mode; - ir_graph *irg = env->irg; - ir_node *block = env->block; /* const_op: tarval or SymConst? */ if (tv) { @@ -432,20 +545,20 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */ DB((mod, LEVEL_2, "Sub(1) to Dec ... ")); - new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode); + new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T); + normal_sub = 0; } else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */ DB((mod, LEVEL_2, "Sub(-1) to Inc ... ")); - new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode); + new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T); + normal_sub = 0; } - else - normal_sub = 1; } - else - normal_sub = 1; - if (normal_sub) - new_op = new_rd_ia32_Sub_i(dbg, irg, block, expr_op, mode); + if (normal_sub) { + new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T); + set_ia32_Immop_attr(new_op, const_op); + } return new_op; } @@ -453,18 +566,61 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node /** * Creates an ia32 Sub. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Sub node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Sub node */ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - if (mode_is_float(env->mode)) { - return new_rd_ia32_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode); + ir_node *new_op = NULL; + dbg_info *dbg = env->dbg; + ir_mode *mode = env->mode; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + ir_node *expr_op, *imm_op; + + imm_op = get_immediate_op(NULL, op2); + expr_op = get_expr_op(op1, op2); + + assert((expr_op || imm_op) && "invalid operands"); + + if (mode_is_float(mode)) { + return gen_binop(env, op1, op2, new_rd_ia32_fSub); } - return new_rd_ia32_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode); + else { + /* integer SUB */ + if (!expr_op) { + /* No expr_op means, that we have two const - one symconst and */ + /* one tarval or another symconst - because this case is not */ + /* covered by constant folding */ + + new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode); + add_ia32_am_offs(new_op, get_ia32_cnst(op1)); + sub_ia32_am_offs(new_op, get_ia32_cnst(op2)); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Source); + set_ia32_op_type(new_op, ia32_AddrModeS); + } + else if (imm_op) { + /* This is expr - const */ + new_op = gen_imm_Sub(env, expr_op, imm_op); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Dest); + } + else { + /* This is a normal sub */ + new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T); + + /* set AM support */ + set_ia32_am_support(new_op, ia32_am_Full); + } + } + + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -479,7 +635,7 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { * @param dm_flav flavour_Div/Mod/DivMod * @return The created ia32 DivMod node */ -static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, op_flavour_t dm_flav) { +static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) { ir_node *res, *proj; ir_node *edx_node, *cltd; ir_node *in_keep[1]; @@ -506,13 +662,13 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir if (mode_is_signed(mode)) { /* in signed mode, we need to sign extend the dividend */ - cltd = new_rd_ia32_Cltd(dbg, irg, block, dividend, mode_T); + cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T); dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX); edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX); } else { edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu); - set_ia32_Const_type(edx_node, asmop_Const); + set_ia32_Const_type(edx_node, ia32_Const); set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu)); } @@ -535,7 +691,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div); } - be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep); + be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep); } return res; @@ -572,102 +728,55 @@ static ir_node *gen_DivMod(ia32_transform_env_t *env, ir_node *op1, ir_node *op2 /** * Creates an ia32 floating Div. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 fDiv node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 fDiv node */ static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_binop(env, op1, op2, new_rd_ia32_fDiv); } -/** - * Creates an ia32 Shl with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Shl_i node - */ -static ir_node *gen_imm_Shl(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_Shl_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 Shl. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Shl node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Shl node */ static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl); } -/** - * Creates an ia32 Shr with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Shr_i node - */ -static ir_node *gen_imm_Shr(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_Shr_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 Shr. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Shr node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Shr node */ static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr); } -/** - * Creates an ia32 Shrs with immediate. - * - * @param dbg firm dbg - * @param block the block the new node should belong to - * @param expr_op operator - * @param mode node mode - * @return the created ia23 Shrs_i node - */ -static ir_node *gen_imm_Shrs(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_Shrs_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 Shrs. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 Shrs node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 Shrs node */ static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs); } @@ -675,15 +784,13 @@ static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) /** * Creates an ia32 RotL. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 RotL node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 RotL node */ static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_RotL(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL); } @@ -693,43 +800,24 @@ static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) * NOTE: There is no RotR with immediate because this would always be a RotL * "imm-mode_size_bits" which can be pre-calculated. * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 RotR node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 RotR node */ static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { - return new_rd_ia32_RotR(env->dbg, env->irg, env->block, op1, op2, env->mode); + return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR); } -/** - * Transforms a Rot with immediate into an ia32 RotL with immediate - * as the Firm Rot is a RotL (see NOTE on RotR with immediate above). - * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 RotL node - */ -static ir_node *gen_imm_Rot(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) { - return new_rd_ia32_RotL_i(env->dbg, env->irg, env->block, expr_op, env->mode); -} - /** * Creates an ia32 RotR or RotL (depending on the found pattern). * - * @param dbg firm node dbg - * @param block the block the new node should belong to - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @return the created ia32 RotL or RotR node + * @param env The transformation environment + * @param op1 The first operator + * @param op2 The second operator + * @return The created ia32 RotL or RotR node */ static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { ir_node *rotate = NULL; @@ -738,178 +826,56 @@ static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e", that means we can create a RotR instead of an Add and a RotL */ - if (is_ia32_Add_i(op2)) { - ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus? + if (is_Proj(op2)) { + ir_node *pred = get_Proj_pred(op2); - if (is_ia32_Minus(minus)) { - tarval *tv = get_ia32_Immop_tarval(op2); - long bits = get_mode_size_bits(env->mode); + if (is_ia32_Add(pred)) { + ir_node *pred_pred = get_irn_n(pred, 2); + tarval *tv = get_ia32_Immop_tarval(pred); + long bits = get_mode_size_bits(env->mode); - if (tarval_is_long(tv) && get_tarval_long(tv) == bits) { - DB((env->mod, LEVEL_1, "RotL into RotR ... ")); - rotate = gen_RotR(env, op1, get_irn_n(minus, 0)); + if (is_Proj(pred_pred)) { + pred_pred = get_Proj_pred(pred_pred); } - } - } - - if (!rotate) - rotate = gen_RotL(env, op1, op2); - - return rotate; -} - - - -/** - * Transforms commutative operations (op_Add, op_And, op_Or, op_Eor) - * and non-commutative operations with com == 0 (op_Sub, op_Shl, op_Shr, op_Shrs, op_Rot) - * - * @param mod the debug module - * @param block the block node belongs to - * @param node the node to transform - * @param op1 first operator - * @param op2 second operator - * @param mode node mode - * @param com flag if op is commutative - * @return the created assembler node - */ -static ir_node *gen_arith_Op(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, int com) { - firm_dbg_module_t *mod = env->mod; - ir_node *node = env->irn; - ir_node *imm_op = NULL; - ir_node *expr_op = NULL; - ir_node *asm_node = NULL; - opcode opc = get_irn_opcode(node); - ir_op *op = get_irn_op(node); - -#undef GENOP -#undef GENOPI -#undef GENOPI_SETATTR -#define GENOP(a) case iro_##a: asm_node = gen_##a(env, op1, op2); break -#define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); break -#define GENOPI_SETATTR(a) case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); set_ia32_Immop_attr(asm_node, imm_op); break - - if (com) - imm_op = get_immediate_op(op1, op2); - else - imm_op = get_immediate_op(NULL, op2); - - expr_op = get_expr_op(op1, op2); - /* TODO: Op(Const, Const) support */ - if (is_ia32_Const(op1) && is_ia32_Const(op2)) { - DB((mod, LEVEL_2, "%+F(Const, Const) -> binop ... ", get_irn_opname(node))); - imm_op = NULL; - } - - /* There are arithmetic operations which can't take an immediate */ - switch(opc) { - case iro_Div: - case iro_Mod: - case iro_DivMod: - DB((mod, LEVEL_2, "Div/Mod/DivMod imm -> binop ... ")); - imm_op = NULL; - break; - default: - if (op == get_op_Min() || op == get_op_Max()) { - DB((mod, LEVEL_2, "MIN/MAX imm -> binop ... ")); - imm_op = NULL; + if (is_ia32_Minus(pred_pred) && + tarval_is_long(tv) && + get_tarval_long(tv) == bits) + { + DB((env->mod, LEVEL_1, "RotL into RotR ... ")); + rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2)); } - break; - } - DB((mod, LEVEL_1, "(%+F -- %+F) ... ", op1, op2)); - - if (!mode_is_float(env->mode) && imm_op) { - DB((mod, LEVEL_1, "immop ... ")); - - switch(opc) { - GENOPI_SETATTR(Add); - GENOPI(Mul); - GENOPI_SETATTR(And); - GENOPI_SETATTR(Or); - GENOPI_SETATTR(Eor); - - GENOPI_SETATTR(Sub); - GENOPI_SETATTR(Shl); - GENOPI_SETATTR(Shr); - GENOPI_SETATTR(Shrs); - GENOPI_SETATTR(Rot); - default: - if (op == get_op_Mulh()) { - asm_node = gen_imm_Mulh(env, expr_op, imm_op); - } - else { - assert("binop_i: THIS SHOULD NOT HAPPEN"); - } } } - else { - DB((mod, LEVEL_1, "binop ... ")); - - switch(opc) { - GENOP(Add); - GENOP(Mul); - GENOP(And); - GENOP(Or); - GENOP(Eor); - - GENOP(Quot); - - GENOP(Div); - GENOP(Mod); - GENOP(DivMod); - - GENOP(Sub); - GENOP(Shl); - GENOP(Shr); - GENOP(Shrs); - GENOP(Rot); - default: - if (op == get_op_Max()) { - asm_node = gen_Max(env, op1, op2); - } - else if (op == get_op_Min()) { - asm_node = gen_Min(env, op1, op2); - } - else if (op == get_op_Mulh()) { - asm_node = gen_Mulh(env, op1, op2); - } - else { - assert("binop: THIS SHOULD NOT HAPPEN"); - } - } + + if (!rotate) { + rotate = gen_RotL(env, op1, op2); } - return asm_node; + return rotate; } -#undef GENOP -#undef GENOPI -#undef GENOPI_SETATTR /** * Transforms a Minus node. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Minus node - * @param op operator - * @param mode node mode - * @return the created ia32 Minus node + * @param env The transformation environment + * @param op The operator + * @return The created ia32 Minus node */ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { - if (is_ia32_Minus(op) || is_ia32_fMinus(op)) { - DB((env->mod, LEVEL_1, "--(e) to e ...")); - return get_irn_n(op, 0); + ir_node *new_op; + + if (mode_is_float(env->mode)) { + assert(0); } else { - if (mode_is_float(env->mode)) { - return new_rd_ia32_fMinus(env->dbg, env->irg, env->block, op, env->mode); - } - return new_rd_ia32_Minus(env->dbg, env->irg, env->block, op, env->mode); + new_op = gen_unop(env, op, new_rd_ia32_Minus); } + + return new_op; } @@ -917,12 +883,9 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { /** * Transforms a Conv node. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Conv node - * @param op operator - * @param mode node mode - * @return the created ia32 Conv node + * @param env The transformation environment + * @param op The operator + * @return The created ia32 Conv node */ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) { return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode); @@ -933,15 +896,21 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) { /** * Transforms a Not node. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Not node - * @param op operator - * @param mode node mode - * @return the created ia32 Not node + * @param env The transformation environment + * @param op The operator + * @return The created ia32 Not node */ static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) { - return new_rd_ia32_Not(env->dbg, env->irg, env->block, op, env->mode); + ir_node *new_op; + + if (mode_is_float(env->mode)) { + assert(0); + } + else { + new_op = gen_unop(env, op, new_rd_ia32_Not); + } + + return new_op; } @@ -949,12 +918,9 @@ static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) { /** * Transforms an Abs node. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Abs node - * @param op operator - * @param mode node mode - * @return the created ia32 Abs node + * @param env The transformation environment + * @param op The operator + * @return The created ia32 Abs node */ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { ir_node *res, *p_eax, *p_edx; @@ -962,12 +928,20 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { ir_mode *mode = env->mode; ir_graph *irg = env->irg; ir_node *block = env->block; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); - res = new_rd_ia32_Cltd(dbg, irg, block, op, mode_T); + if (mode_is_float(mode)) { + assert(0); + } + + res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T); p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX); p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX); - res = new_rd_ia32_Eor(dbg, irg, block, p_eax, p_edx, mode); - res = new_rd_ia32_Sub(dbg, irg, block, res, p_edx, mode); + res = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, p_eax, p_edx, nomem, mode_T); + res = new_rd_Proj(dbg, irg, block, res, mode, 0); + res = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, res, p_edx, nomem, mode_T); + res = new_rd_Proj(dbg, irg, block, res, mode, 0); return res; } @@ -984,12 +958,13 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { * @return the created ia32 Load node */ static ir_node *gen_Load(ia32_transform_env_t *env) { - ir_node *node = env->irn; + ir_node *node = env->irn; + ir_node *noreg = be_new_NoReg(env->irg); if (mode_is_float(env->mode)) { - return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); + return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); } - return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode); + return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); } @@ -1004,12 +979,13 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { * @return the created ia32 Store node */ ir_node *gen_Store(ia32_transform_env_t *env) { - ir_node *node = env->irn; + ir_node *node = env->irn; + ir_node *noreg = be_new_NoReg(env->irg); if (mode_is_float(env->mode)) { - return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); + return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); } - return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode); + return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); } @@ -1028,7 +1004,7 @@ static ir_node *gen_Call(ia32_transform_env_t *env) { ir_node **in; ir_node *new_call, *sync; int i, j, n_new_call_in, ignore = 0; - asmop_attr *attr; + ia32_attr_t *attr; dbg_info *dbg = env->dbg; ir_graph *irg = env->irg; ir_node *block = env->block; @@ -1124,13 +1100,13 @@ static ir_node *gen_Call(ia32_transform_env_t *env) { /* two results only appear when a 64bit int result is broken up into two 32bit results */ if (n_res == 1) { if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0)))) - attr->out_req[0] = &ia32_default_req_ia32_floating_point_xmm0; + attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0; else - attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax; + attr->out_req[0] = &ia32_default_req_ia32_gp_eax; } else if (n_res == 2) { - attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax; - attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx; + attr->out_req[0] = &ia32_default_req_ia32_gp_eax; + attr->out_req[1] = &ia32_default_req_ia32_gp_edx; } /* stack parameter has no OUT register */ @@ -1144,22 +1120,21 @@ static ir_node *gen_Call(ia32_transform_env_t *env) { /** * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Cond node - * @param mode mode of the Cond + * @param env The transformation environment * @return The transformed node. */ static ir_node *gen_Cond(ia32_transform_env_t *env) { - dbg_info *dbg = env->dbg; - ir_graph *irg = env->irg; - ir_node *block = env->block; - ir_node *node = env->irn; - ir_node *sel = get_Cond_selector(node); - ir_mode *sel_mode = get_irn_mode(sel); - ir_node *res = NULL; - ir_node *pred = NULL; - ir_node *cmp_a, *cmp_b, *cnst, *expr; + dbg_info *dbg = env->dbg; + ir_graph *irg = env->irg; + ir_node *block = env->block; + ir_node *node = env->irn; + ir_node *sel = get_Cond_selector(node); + ir_mode *sel_mode = get_irn_mode(sel); + ir_node *res = NULL; + ir_node *pred = NULL; + ir_node *noreg = be_new_NoReg(irg); + ir_node *nomem = new_NoMem(); + ir_node *cmp_a, *cmp_b, *cnst, *expr; if (is_Proj(sel) && sel_mode == mode_b) { pred = get_Proj_pred(sel); @@ -1173,17 +1148,17 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) { expr = get_expr_op(cmp_a, cmp_b); if (cnst && expr) { - res = new_rd_ia32_CondJmp_i(dbg, irg, block, expr, mode_T); + res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T); set_ia32_Immop_attr(res, cnst); } else { - res = new_rd_ia32_CondJmp(dbg, irg, block, cmp_a, cmp_b, mode_T); + res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T); } set_ia32_pncode(res, get_Proj_proj(sel)); } else { - res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T); + res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T); set_ia32_pncode(res, get_Cond_defaultProj(node)); } @@ -1320,36 +1295,6 @@ static ir_node *gen_Proj(ia32_transform_env_t *env) { -/** - * Transforms an Alloc node into either ia32_Alloca or ia32_Malloc. - */ -static ir_node *gen_Alloc(ia32_transform_env_t *env) { - dbg_info *dbg = env->dbg; - ir_graph *irg = env->irg; - ir_node *block = env->block; - ir_node *irn = env->irn; - ir_mode *mode = env->mode; - ir_node *size = get_Alloc_size(irn); - ir_node *mem = get_Alloc_mem(irn); - ir_node *res; - - if (get_Alloc_where(irn) == stack_alloc) { - if (is_ia32_Const(size)) { - res = new_rd_ia32_Alloca_i(dbg, irg, block, mem, mode); - set_ia32_Immop_attr(res, size); - } - else { - res = new_rd_ia32_Alloca(dbg, irg, block, size, mem, mode); - } - } - else { - assert(0 && "malloc should be already lowered"); - res = NULL; - } - - return res; -} - /********************************************************* * _ _ _ * (_) | | (_) @@ -1387,31 +1332,31 @@ void ia32_transform_node(ir_node *node, void *env) { tenv.mode = get_irn_mode(node); tenv.cg = cgenv; -#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break -#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break -#define BINOP_COM(a) case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 1); break -#define BINOP_NCOM(a) case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 0); break -#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break -#define IGN(a) case iro_##a: break -#define BAD(a) case iro_##a: goto bad +#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break +#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break +#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break +#define IGN(a) case iro_##a: break +#define BAD(a) case iro_##a: goto bad DBG((tenv.mod, LEVEL_1, "check %+F ... ", node)); switch (code) { - BINOP_COM(Add); - BINOP_COM(Mul); - BINOP_COM(And); - BINOP_COM(Or); - BINOP_COM(Eor); - - BINOP_NCOM(Sub); - BINOP_NCOM(Shl); - BINOP_NCOM(Shr); - BINOP_NCOM(Shrs); - BINOP_NCOM(Quot); - BINOP_NCOM(Div); - BINOP_NCOM(Mod); - BINOP_NCOM(DivMod); + BINOP(Add); + BINOP(Sub); + BINOP(Mul); + BINOP(And); + BINOP(Or); + BINOP(Eor); + + BINOP(Shl); + BINOP(Shr); + BINOP(Shrs); + + BINOP(Quot); + + BINOP(Div); + BINOP(Mod); + BINOP(DivMod); UNOP(Minus); UNOP(Conv); @@ -1420,10 +1365,11 @@ void ia32_transform_node(ir_node *node, void *env) { GEN(Load); GEN(Store); - GEN(Call); GEN(Cond); + GEN(Proj); - GEN(Alloc); + GEN(Call); + IGN(Alloc); IGN(Block); IGN(Start); @@ -1456,11 +1402,14 @@ void ia32_transform_node(ir_node *node, void *env) { BAD(CopyB); default: - if (get_irn_op(node) == get_op_Max() || - get_irn_op(node) == get_op_Min() || - get_irn_op(node) == get_op_Mulh()) - { - asm_node = gen_arith_Op(&tenv, get_irn_n(node, 0), get_irn_n(node, 1), 1); + if (get_irn_op(node) == get_op_Max()) { + asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); + } + else if (get_irn_op(node) == get_op_Min()) { + asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); + } + else if (get_irn_op(node) == get_op_Mulh()) { + asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); } break; bad: -- 2.20.1