+ if(reg[0] != '\0') {
+ ia32_emit_char(env, '%');
+ ia32_emit_string(env, reg);
+ }
+ ia32_emit_finish_line(env, node);
+
+ ia32_emit_cstring(env, "\tfnstsw %ax");
+ ia32_emit_finish_line(env, node);
+ ia32_emit_cstring(env, "\tsahf");
+ ia32_emit_finish_line(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)) {
+ ia32_emit_cstring(env, "\tcmp ");
+ ia32_emit_source_register(env, node, 1);
+ ia32_emit_cstring(env, ", ");
+ ia32_emit_source_register(env, node, 0);
+ } else if (is_ia32_xCmpCMov(node)) {
+ ia32_emit_cstring(env, "\tucomis");
+ ia32_emit_mode_suffix(env, get_irn_mode(node));
+ ia32_emit_char(env, ' ');
+ ia32_emit_source_register(env, node, 1);
+ ia32_emit_cstring(env, ", ");
+ ia32_emit_source_register(env, node, 0);
+ } else if (is_PsiCondCMov) {
+ /* omit compare because flags are already set by And/Or */
+ ia32_emit_cstring(env, "\ttest ");
+ ia32_emit_source_register(env, node, 0);
+ ia32_emit_cstring(env, ", ");
+ ia32_emit_source_register(env, node, 0);
+ } else {
+ assert(0 && "unsupported CMov");
+ }
+ ia32_emit_finish_line(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) {
+ ia32_emit_cstring(env, "\tmovl ");
+ ia32_emit_dest_register(env, node, 2);
+ ia32_emit_cstring(env, ", ");
+ ia32_emit_dest_register(env, node, 0);
+ } else {
+ ia32_emit_cstring(env, "\tmovl ");
+ ia32_emit_source_register(env, node, 3);
+ ia32_emit_cstring(env, ", ");
+ ia32_emit_dest_register(env, node, 0);
+ }
+ ia32_emit_finish_line(env, node);
+ }