- flipped = 1;
- pnc = get_negated_pnc(pnc, mode);
- }
-
- /* in case of unordered compare, check for parity */
- if (pnc & pn_Cmp_Uo) {
- be_emit_cstring(env, "\tjp ");
- ia32_emit_cfop_target(env, proj_true);
- be_emit_finish_line_gas(env, proj_true);
- }
-
- be_emit_cstring(env, "\tj");
- ia32_emit_cmp_suffix(env, pnc);
- be_emit_char(env, ' ');
- ia32_emit_cfop_target(env, proj_true);
- be_emit_finish_line_gas(env, proj_true);
-
- /* the second Proj might be a fallthrough */
- if (get_cfop_target_block(proj_false) != next_block) {
- be_emit_cstring(env, "\tjmp ");
- ia32_emit_cfop_target(env, proj_false);
- be_emit_finish_line_gas(env, proj_false);
- } else {
- be_emit_cstring(env, "\t/* fallthrough to");
- ia32_emit_cfop_target(env, proj_false);
- be_emit_cstring(env, " */");
- be_emit_finish_line_gas(env, proj_false);
- }
-}
-
-/**
- * Emits code for conditional jump.
- */
-static
-void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
- be_emit_cstring(env, "\tcmp ");
- ia32_emit_binop(env, node);
- be_emit_finish_line_gas(env, node);
-
- finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
-}
-
-/**
- * Emits code for conditional jump with two variables.
- */
-static
-void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
- CondJmp_emitter(env, node);
-}
-
-/**
- * Emits code for conditional test and jump.
- */
-static
-void TestJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
- if(is_ia32_ImmSymConst(node) || is_ia32_ImmConst(node)) {
- be_emit_cstring(env, "\ttest $");
- ia32_emit_immediate(env, node);
- be_emit_cstring(env, ", ");
- ia32_emit_source_register(env, node, 0);
- be_emit_finish_line_gas(env, node);
- } else {
- be_emit_cstring(env, "\ttest ");
- ia32_emit_source_register(env, node, 1);
- be_emit_cstring(env, ", ");
- ia32_emit_source_register(env, node, 0);
- be_emit_finish_line_gas(env, node);
- }
- finish_CondJmp(env, node, mode_Iu, get_ia32_pncode(node));
-}
-
-/**
- * Emits code for conditional test and jump with two variables.
- */
-static
-void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
- TestJmp_emitter(env, node);
-}
-
-static
-void emit_ia32_CJmp(ia32_emit_env_t *env, const ir_node *node) {
- be_emit_cstring(env, "/* omitted redundant test */");
- be_emit_finish_line_gas(env, node);
-
- finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
-}
-
-static
-void emit_ia32_CJmpAM(ia32_emit_env_t *env, const ir_node *node) {
- be_emit_cstring(env, "/* omitted redundant test/cmp */");
- be_emit_finish_line_gas(env, node);
-
- finish_CondJmp(env, node, mode_Is, get_ia32_pncode(node));
-}
-
-/**
- * Emits code for conditional SSE floating point jump with two variables.
- */
-static
-void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
- be_emit_cstring(env, "\tucomi");
- ia32_emit_xmm_mode_suffix(env, node);
- be_emit_char(env, ' ');
- ia32_emit_binop(env, node);
- be_emit_finish_line_gas(env, node);
-
- finish_CondJmp(env, node, mode_F, get_ia32_pncode(node));
-}
-
-/**
- * Emits code for conditional x87 floating point jump with two variables.
- */
-static
-void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
- ia32_attr_t *attr = get_ia32_attr(node);
- const char *reg = attr->x87[1]->name;
- long pnc = get_ia32_pncode(node);
-
- switch (get_ia32_irn_opcode(node)) {
- case iro_ia32_fcomrJmp:
- pnc = get_inversed_pnc(pnc);
- reg = attr->x87[0]->name;
- case iro_ia32_fcomJmp:
- default:
- be_emit_cstring(env, "\tfucom ");
- break;
- case iro_ia32_fcomrpJmp:
- pnc = get_inversed_pnc(pnc);
- reg = attr->x87[0]->name;
- case iro_ia32_fcompJmp:
- be_emit_cstring(env, "\tfucomp ");
- break;
- case iro_ia32_fcomrppJmp:
- pnc = get_inversed_pnc(pnc);
- case iro_ia32_fcomppJmp:
- be_emit_cstring(env, "\tfucompp ");
- reg = "";
- break;
- }
-
- if(reg[0] != '\0') {
- be_emit_char(env, '%');
- be_emit_string(env, reg);
- }
- be_emit_finish_line_gas(env, node);
-
- be_emit_cstring(env, "\tfnstsw %ax");
- be_emit_finish_line_gas(env, node);
- be_emit_cstring(env, "\tsahf");
- be_emit_finish_line_gas(env, node);
-
- finish_CondJmp(env, node, mode_E, pnc);
-}
-
-static
-void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
- long pnc = get_ia32_pncode(node);
- int is_PsiCondCMov = is_ia32_PsiCondCMov(node);
- int idx_left = 2 - is_PsiCondCMov;
- int idx_right = 3 - is_PsiCondCMov;
- const arch_register_t *in1, *in2, *out;
-
- out = arch_get_irn_register(env->arch_env, node);
- in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_left));
- in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, idx_right));
-
- /* we have to emit the cmp first, because the destination register */
- /* could be one of the compare registers */
- if (is_ia32_CmpCMov(node)) {
- be_emit_cstring(env, "\tcmp ");
- ia32_emit_source_register(env, node, 1);
- be_emit_cstring(env, ", ");
- ia32_emit_source_register(env, node, 0);
- } else if (is_ia32_xCmpCMov(node)) {
- be_emit_cstring(env, "\tucomis");
- ia32_emit_mode_suffix(env, get_irn_mode(node));
- be_emit_char(env, ' ');
- ia32_emit_source_register(env, node, 1);
- be_emit_cstring(env, ", ");
- ia32_emit_source_register(env, node, 0);
- } else if (is_PsiCondCMov) {
- /* omit compare because flags are already set by And/Or */
- be_emit_cstring(env, "\ttest ");
- ia32_emit_source_register(env, node, 0);
- be_emit_cstring(env, ", ");
- ia32_emit_source_register(env, node, 0);
- } else {
- assert(0 && "unsupported CMov");
- }
- be_emit_finish_line_gas(env, node);
-
- if (REGS_ARE_EQUAL(out, in2)) {
- /* best case: default in == out -> do nothing */
- } else if (REGS_ARE_EQUAL(out, in1)) {
- ir_node *n = (ir_node*) node;
- /* true in == out -> need complement compare and exchange true and default in */
- ir_node *t = get_irn_n(n, idx_left);
- set_irn_n(n, idx_left, get_irn_n(n, idx_right));
- set_irn_n(n, idx_right, t);
-
- pnc = get_negated_pnc(pnc, get_irn_mode(node));
- } else {
- /* out is different from in: need copy default -> out */
- if (is_PsiCondCMov) {
- be_emit_cstring(env, "\tmovl ");
- ia32_emit_dest_register(env, node, 2);
- be_emit_cstring(env, ", ");
- ia32_emit_dest_register(env, node, 0);