X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=192ecbe7178f576e190b0f6d1efe1703d21fb61b;hb=48071aea23fabc99044488d12757f274bc956fae;hp=b621521cce2bedd2b382147d4224772e31cbe430;hpb=059f8c6eaa207f0b5355401c7f50519dea80dc3c;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index b621521cc..192ecbe71 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1139,41 +1139,80 @@ static void emit_ia32_xCmp(ir_node *irn, ia32_emit_env_t *env) { FILE *F = env->out; const lc_arg_env_t *arg_env = ia32_get_arg_env(); int sse_pnc = -1; + long pnc = get_ia32_pncode(irn); + long unord = pnc & pn_Cmp_Uo; char cmd_buf[SNPRINTF_BUF_LEN]; char cmnt_buf[SNPRINTF_BUF_LEN]; - switch (get_ia32_pncode(irn)) { + switch (pnc) { case pn_Cmp_Leg: /* odered */ sse_pnc = 7; break; case pn_Cmp_Uo: /* unordered */ sse_pnc = 3; break; - case pn_Cmp_Ue: /* == */ + case pn_Cmp_Ue: + case pn_Cmp_Eq: /* == */ sse_pnc = 0; break; - case pn_Cmp_Ul: /* < */ + case pn_Cmp_Ul: + case pn_Cmp_Lt: /* < */ sse_pnc = 1; break; - case pn_Cmp_Ule: /* <= */ + case pn_Cmp_Ule: + case pn_Cmp_Le: /* <= */ sse_pnc = 2; break; - case pn_Cmp_Ug: /* > */ + case pn_Cmp_Ug: + case pn_Cmp_Gt: /* > */ sse_pnc = 6; break; - case pn_Cmp_Uge: /* >= */ + case pn_Cmp_Uge: + case pn_Cmp_Ge: /* >= */ sse_pnc = 5; break; - case pn_Cmp_Ne: /* != */ + case pn_Cmp_Ne: + case pn_Cmp_Lg: /* != */ sse_pnc = 4; break; } - assert(sse_pnc >= 0 && "unsupported floating point compare"); - - lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmps%M %s, %d", irn, ia32_emit_binop(irn, env), sse_pnc); - lc_esnprintf(arg_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* SSE compare with result in %1D */", irn); + assert(sse_pnc >= 0 && "unsupported compare"); + + if (unord && sse_pnc != 3) { + /* + We need a separate compare against unordered. + Quick and Dirty solution: + - get some memory on stack + - compare + - store result + - compare + - and result and stored result + - cleanup stack + */ + snprintf(cmd_buf, SNPRINTF_BUF_LEN, "sub %%esp, 8"); + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* reserve some space for unordered compare result */"); + IA32_DO_EMIT(NULL); + snprintf(cmd_buf, SNPRINTF_BUF_LEN, "cmpsd %s, 3", ia32_emit_binop(irn, env)); + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* SSE compare: unordered */"); + IA32_DO_EMIT(NULL); + lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "movsd [%%esp], %1D", irn); + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* store compare result */"); + IA32_DO_EMIT(NULL); + } + + snprintf(cmd_buf, SNPRINTF_BUF_LEN, "cmpsd %s, %d", ia32_emit_binop(irn, env), sse_pnc); + lc_esnprintf(arg_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* SSE compare (%+F) with result in %1D */", irn, irn); IA32_DO_EMIT(irn); + + if (unord && sse_pnc != 3) { + lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "andpd %1D, [%%esp]", irn); + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* build the final result */"); + IA32_DO_EMIT(NULL); + snprintf(cmd_buf, SNPRINTF_BUF_LEN, "add %%esp, 8"); + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* free allocated space */"); + IA32_DO_EMIT(NULL); + } } /********************************************************* @@ -1616,19 +1655,6 @@ static void emit_be_Call(const ir_node *irn, ia32_emit_env_t *emit_env) { IA32_DO_EMIT(irn); } -/** - * Emits code to increase stack pointer. - */ -static void emit_be_AddSP(const ir_node *irn, ia32_emit_env_t *emit_env) { - FILE *F = emit_env->out; - char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN]; - - lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "sub %1D, %2S", irn, irn); - snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* reserve space on stack */"); - - IA32_DO_EMIT(irn); -} - /** * Emits code to increase stack pointer. */ @@ -1758,6 +1784,30 @@ static void emit_ia32_Const(const ir_node *n, ia32_emit_env_t *env) { lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, cmnt_buf, n, n); } +/** + * Emits code to increase stack pointer. + */ +static void emit_ia32_AddSP(const ir_node *irn, ia32_emit_env_t *emit_env) { + FILE *F = emit_env->out; + char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN]; + + if (is_ia32_ImmConst(irn)) { + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "sub %1D, %C", irn, irn); + } + else if (is_ia32_ImmSymConst(irn)) { + if (get_ia32_op_type(irn) == ia32_Normal) + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "sub %1D, OFFSET_FLAT:%C", irn, irn); + else /* source address mode */ + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "sub %1D, [%s%s]", irn, get_id_str(get_ia32_am_sc(irn)), get_ia32_am_offs(irn)); + } + else { + lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "sub %1D, %2S", irn, irn); + } + snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* reserve space on stack */"); + + IA32_DO_EMIT(irn); +} + static void emit_be_Return(const ir_node *n, ia32_emit_env_t *env) { FILE *F = env->out; const lc_arg_env_t *arg_env = ia32_get_arg_env(); @@ -1819,6 +1869,7 @@ static void ia32_register_emitters(void) { IA32_EMIT(Conv_I2I); IA32_EMIT(Conv_I2I8Bit); IA32_EMIT(Const); + IA32_EMIT(AddSP); IA32_EMIT(xCmp); IA32_EMIT(xCmpSet); IA32_EMIT(xCmpCMov); @@ -1832,7 +1883,6 @@ static void ia32_register_emitters(void) { /* benode emitter */ BE_EMIT(Call); - BE_EMIT(AddSP); BE_EMIT(IncSP); BE_EMIT(SetSP); BE_EMIT(Copy); @@ -1917,7 +1967,7 @@ static void ia32_emit_align_label(FILE *F, cpu_support cpu) { unsigned align; unsigned maximum_skip; /* gcc doesn't emit alignment for p4 ?*/ - if (cpu == arch_pentium_4) + if (cpu == arch_pentium_4) return; switch (cpu) { @@ -1943,7 +1993,10 @@ static void ia32_emit_align_label(FILE *F, cpu_support cpu) { static void ia32_gen_block(ir_node *block, void *env) { ia32_emit_env_t *emit_env = env; const ir_node *irn; + char cmd_buf[SNPRINTF_BUF_LEN]; + char cmnt_buf[SNPRINTF_BUF_LEN]; int need_label = block != get_irg_start_block(get_irn_irg(block)); + FILE *F = emit_env->out; if (! is_Block(block)) return; @@ -1955,10 +2008,40 @@ static void ia32_gen_block(ir_node *block, void *env) { } if (need_label) { + int i, arity; + char* predstring = cmnt_buf; + size_t cmntsize; + int res; + ia32_emit_align_label(emit_env->out, emit_env->isa->opt_arch); - fprintf(emit_env->out, BLOCK_PREFIX("%ld:\n"), get_irn_node_nr(block)); + + ir_snprintf(cmd_buf, sizeof(cmd_buf), BLOCK_PREFIX("%d:"), + get_irn_node_nr(block)); + + /* emit list of pred blocks in comment */ + cmntsize = sizeof(cmnt_buf); + res = snprintf(predstring, cmntsize, "/* preds: "); + cmntsize -= res; + predstring += res; + + arity = get_irn_arity(block); + for(i = 0; i < arity; ++i) { + ir_node *predblock = get_Block_cfgpred_block(block, i); + res = snprintf(predstring, cmntsize, " %ld", get_irn_node_nr(predblock)); + cmntsize -= res; + predstring += res; + if(cmntsize <= 3) + break; + } + if(cmntsize < 3) { + predstring = cmnt_buf + sizeof(cmnt_buf) - 3; + cmntsize = 3; + } + snprintf(predstring, cmntsize, "*/"); + fprintf(F, "%-43s %-60s\n", cmd_buf, cmnt_buf); } + /* emit the contents of the block */ sched_foreach(block, irn) { ia32_emit_node(irn, env); }